prototype和__proto__

Object/Function/Array/String 原型链

注入一个奇怪的观念:

  • Function.prototype 独立于/先于 Function 存在;
  • Object.prototype 独立于/先于 Object 存在

prototype和__proto__

1
2
3
4
5
Object.prototype.__proto__ ; // null 因此 Object.prototype 是原型链的终点
Function.__proto__ === Function.prototype; // true
Object.__proto__ === Function.prototype; // true
Array.__proto__ === Function.prototype; // true
String.__proto__ === Function.prototype; // true

由上图我们可以看出原型链是 Object.prototype –> Function.prototype –> Object/Array/String/Function……

类和实例

在JS中,类实际就是一个函数。

对类进行实例化,采用关键字 new,例子如下:

1
2
3
4
5
function Animal(name) {
this.name = name;
}
Animal.prototype.say = "Hello";
let animal = new Animal("animal");

以上 Animal是类,animal 是实例

输入:animal

输出:prototype和__proto__

  • 定义一个函数的时候,js会自动给这个函数添加一个 prototype 的属性,值是空对象。
  • 每一个JS对象都有一个 __proto__ 属性,但 prototype属性只有函数才有。

我们将上面的代码画成图:

prototype和__proto__

可以看出:

1
animal.__proto__ === Animal.prototype; // true

实例继承构造函数prototype的所有属性和方法。

我们可以通过实例去使用构造函数的属性和方法,如下:

1
2
console.log(animal.say); // Hello
console.log(animal.constructor === Animal); // true,constructor 属性指代这个类
  • instanceof : 用于判断一个变量是否某个对象的实例 [instance:实例,例子]
  • thisprototype 获取到的属性和方法,有什么区别?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Animal(name) {
    this.name = name;
    }
    Animal.prototype.say = "hello"
    let dog = new Animal("dog")
    console.log(dog.name); // dog
    console.log(dog.say); // hello
同样是能获取到所继承的类的属性,但有一个弊端是当有多个对象继承该类时,只是用 `this` 的话,资源没办法共享,所以采用 `prototype` 资源的共享,当需要修改 `prototype` 中的某个属性或方法时,只需要 `Animal.prototype.say = "hi"`

参考

类和继承

类的继承可以用 callapply 方法实现,它们的异同如下:

  • 相同点:两个方法产生的作用是完全一样的,用于改变this指向
  • 不同点:方法传递的参数不同