原型基础
1 2
| function Foo(){}; console.log(Foo.prototype.constructor === Foo)
|
1 2 3
| function Foo(); var foo = new Foo(); console.log(foo.__proto__ === Foo.prototype) //true
|
1 2
| function Foo(){}; console.log(Foo.prototype.__proto__ === Object.prototype);
|
Foo.prototype 是Object预创建的一个对象,是Object创建的一个实例,所以,Foo.prototype._proto 是Object.prototype的引用
原型链:
1 2
| __proto__ __proto__ __proto__ foo ---------- Foo.prototype --------------- Object.prototype ------------ null
|
在javascript中,函数式特殊对象,所有函数都是构造函数Function的实例
1 2 3
| function Foo() {}; console.log(Foo.__proto__ === Object.prototype); console.log(Foo.__proto__ === Function.prototype);
|
函数Foo._proto 指向到 Function.prototype, 说明函数 Foo 是 Function的一个实例
1 2 3
| function Foo(){}; console.log(Foo.__proto__ === Function.prototype); console.log(Foo.prototype.__proto__ === Object.prototype);
|
Foo.prototype 是Object预定义的对象,构造函数为Object,所以proto指向 Object.prototype
1 2 3 4 5 6 7 8
| __proto__ __proto__ __proto__ foo ---------- Foo.prototype --------------- Object.prototype ------------ null __proto__ __proto__ __proto__ Foo ---------- Function.prototype --------------- Object.prototype ------------ null __proto__ __proto__ __proto__ Function ------------- Function.prototype --------------- Object.prototype ------------ null __proto__ __proto__ __proto__ Object ------------ Function.prototype --------------- Object.prototype ------------ null
|
Object、Function、Array 等这些函数,他们的构造函数都是 Function 的实例
基于原型链的基础
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function A(){ console.log('A init') } A.prototype.play = function(){ console.log('A play'); } function B(){ console.log('B init') } function C(){}
C.prototype = A.prototype; B.prototype = new C(); C.constructor = C; var B = new B(); B.play();
|
ES6 class
ES6的写法
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 30 31 32 33 34 35 36 37 38
| class Animal { constructor(name,color) { this.name = name; this.color = color; } toString() { console.log('name:' + this.name + ',color:' + this.color);
} } var animal = new Animal('dog','white'); animal.toString();
console.log(animal.hasOwnProperty('name')); console.log(animal.hasOwnProperty('toString')); console.log(animal.__proto__.hasOwnProperty('toString'));
class Cat extends Animal { constructor(action) { super('cat','white'); this.action = action; } toString() { console.log(super.toString()); } }
var cat = new Cat('catch') cat.toString(); console.log(cat instanceof Cat); console.log(cat instanceof Animal);
|
ES5的写法(此处实现为typescript编译)
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 30 31 32 33 34 35 36 37
| var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var Animal = (function () { function Animal(name, color) { this.name = name; this.color = color; } Animal.prototype.toString = function () { console.log('name:' + this.name + ',color:' + this.color); }; return Animal; }()); var Cat = (function (_super) { __extends(Cat, _super); function Cat(action) { var _this = _super.call(this, 'cat', 'white') || this; _this.action = action; return _this; } Cat.prototype.toString = function () { console.log(_super.prototype.toString.call(this)); }; return Cat; }(Animal));
|
类的prototype属性和proto属性
在 class 中。同时具有 proto 和 prototype 两个属性,存在两条继承链。
- 子类的 proto 属性,表示构造函数的继承,总是指向父类。
- 子类的 prototype 的 proto 属性表示方法的继承,总是指向父类的 prototype 属性
1 2 3
| class Cat extends Animal {} console.log(Cat.__proto__ === Animal); console.log(Cat.prototype.__proto__ === Animal.prototype);
|
第一条 Cat.proto === Animal 这条原型链
1 2 3 4 5
| class Cat extends Animal { construcotr() { return Animal.__proto__.call(this); } }
|
第二条对原型链 Cat.prototype.proto === Animal.prototype 完成方法的继承
1
| Cat.prototype.__proto__ = Animal.prototype
|
特殊情况:
1 2 3
| class A extends Object {} console.log(A.__proto__ === Object); console.log(A.prototype.__proto__ === Object.prototype);
|
A继承Object,A的prototype 指向父类Object. A的 prototype.proto 指向父类Object的prototype
1 2 3
| class Cat {} console.log(Cat.__proto__ === Function.prototype); console.log(Cat.prototype.__proto__ === Object.prototype);
|
由于Cat不存在任何继承,就相当于一个普通函数,由于函数都是Function 的实例,所以 Cat.proto指向 Function.prototype. 第二条继承链指向父类(Function.prototype) 的prototype属性,所以 Cat.prototype.proto === Object.prototype. Cat调用后会返回Object实例,所以 A.prototype.proto 指向构造函数(Object)的prototype
1 2 3
| class Cat extends null {}; console.log(Cat.__proto__ === Function.prototype); console.log(Cat.prototype.__proto__ === null);
|
Cat是一个普通函数,所以继承 Function.prototype .第二条继承链不继承任何方法,所以 Cat.prototype.proto == null
原型三角关系 prototype、proto(proto)、constructor
(原型三角关系图地址)[https://www.processon.com/embed/579c671de4b0e645bc6a0c10]
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 30 31 32 33
| ----- ----- |对象| |函数| ----- ----- ------------------------------------------ |代码:function Foo(){};var f1 = new Foo()| ------------------------------------------ ---- ---------- |f1| ------------->|Foo(继承)| ---- ---------- | proto | ∨ --------------- constructor --------- |Foo.prototype| --------------> | Foo | ----------------------proto-------------- | | <-------------- | | | | --------------- prototype --------- | ∨ | | ---------- --------------------- | proto constructor --------->|Function|--prototype -->|Function.prototype | | | | |<-constructor--| | | | ---------- --------------------- ∨ ∨ ∧ | ------------------ constructor ----------- | | |Object.prototype| --------> | Object | | | --- | | <-------- | |---------------------proto--------------- | | ------------------ prototype ----------- | | ∧ | | | | proto -----------------------------------proto------------------------------------------------- | | ------- ----->| null| -------
|
参考链接:
ECMAScript 6 的新特性
https://github.com/maxzhang/maxzhang.github.com/issues/5
http://www.cnblogs.com/xiaohuochai/p/5721552.html