# 1.JavaScript 的原型
  1. Object.create 根据指定的原型创建新对象,原型可以是 null;
  2. Object.getPrototypeOf 获得一个对象的原型;
  3. Object.setPrototypeOf 设置一个对象的原型。
//利用这三个方法,我们可以完全抛开类的思维,利用原型来实现抽象和复用
var cat = {
    say(){
        console.log("meow~");
    },
    jump(){
        console.log("jump");
    }
}

var tiger = Object.create(cat,  {
    say:{
        writable:true,
        configurable:true,
        enumerable:true,
        value:function(){
            console.log("roar!");
        }
    }
})


var anotherCat = Object.create(cat);

anotherCat.say();

var anotherTiger = Object.create(tiger);

anotherTiger.say();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 2.JavaScript 的类

在早期版本(ES3 和之前的版本)的JavaScript中,JS中类的概念是相当弱的,“类”的定义是一个私有属性 [[class]],它仅仅是运行时的一个字符串属性,语言使用者唯一可以访问 [[class]] 属性的方式是Object.prototype.toString

var o = new Object;
var n = new Number;
var s = new String;
var b = new Boolean;
var d = new Date;
var arg = function(){ return arguments }();
var r = new RegExp;
var f = new Function;
var arr = new Array;
var e = new Error;
console.log([o, n, s, b, d, arg, r, f, arr, e].map(v => Object.prototype.toString.call(v))); 

// ["[object Object]", "[object Number]", "[object String]", "[object Boolean]", "[object Date]", "[object Arguments]", "[object RegExp]", "[object Function]", …]
1
2
3
4
5
6
7
8
9
10
11
12
13

在 ES5 开始,[[class]] 私有属性被 Symbol.toStringTag代替

var o = { [Symbol.toStringTag]: "MyObject" }
console.log(o + "");                            //[object MyObject]
console.log(Object.prototype.toString.call(o))  //[object MyObject]

//
let o = 1
console.log(o.__proto__[Symbol.toStringTag])  //undifined,私有字段不能获取自能Object.prototype.toString
o.__proto__[Symbol.toStringTag]="unNumber"
let b=1
console.log(Object.prototype.toString.call(o))  //[object unNumber] 把number的类的字段给改了
console.log(Object.prototype.toString.call(b))  //[object unNumber]
1
2
3
4
5
6
7
8
9
10
11
# new在js面向对象做了哪些
  1. 以构造器的 prototype 属性(注意与私有字段 [[prototype]] 的区分)为原型,创建新对象;
  2. 将this 和调用参数传给构造器,执行;
  3. 如果构造器返回的是对象,则返回,否则返回第一步创建的对象。

function c1(){
    this.p1 = 1;
    this.p2 = function(){
        console.log(this.p1);
    }
} 
var o1 = new c1;
o1.p2();



function c2(){
}
c2.prototype.p1 = 1;
c2.prototype.p2 = function(){
    console.log(this.p1);
}

var o2 = new c2;
o2.p2();

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

//没有 Object.create、Object.setPrototypeOf 的早期版本中,new 运算是唯一一个可以指定 [[prototype]] 的方法

# ES6中的class
class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }

  speak() {
    console.log(this.name + ' barks.');
  }
}

let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.
//在新的 ES 版本中,我们不再需要模拟类了:我们有了光明正大的类,但实际还是原型结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23