js_prototype


原型基础

1
2
function Foo(){};
console.log(Foo.prototype.constructor === Foo) //true
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); // true

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); //false
console.log(Foo.__proto__ === Function.prototype); // true

函数Foo._proto 指向到 Function.prototype, 说明函数 Foo 是 Function的一个实例

1
2
3
function Foo(){};
console.log(Foo.__proto__ === Function.prototype); //true
console.log(Foo.prototype.__proto__ === Object.prototype);//true

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();
//output B init >> A 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 是原型对象上的属性
toString() {
console.log('name:' + this.name + ',color:' + this.color);

}
}

var animal = new Animal('dog','white');
animal.toString();

console.log(animal.hasOwnProperty('name')); //true
console.log(animal.hasOwnProperty('toString')); // false
console.log(animal.__proto__.hasOwnProperty('toString')); // true

class Cat extends Animal {
constructor(action) {
// 子类必须要在constructor中指定super 方法,否则在新建实例的时候会报错.
// 如果没有置顶consructor,默认带super方法的constructor将会被添加、
super('cat','white');
this.action = action;
}
toString() {
console.log(super.toString());
}
}

var cat = new Cat('catch')
cat.toString();

// 实例cat 是 Cat 和 Animal 的实例,和Es5完全一致。
console.log(cat instanceof Cat); // true
console.log(cat instanceof Animal); // true

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;
}
// toString 是原型对象上的属性
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 =
// 子类必须要在constructor中指定super 方法,否则在新建实例的时候会报错.
// 如果没有置顶consructor,默认带super方法的constructor将会被添加、
_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); // true
    console.log(Cat.prototype.__proto__ === Animal.prototype); // true

第一条 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
1
2
3
class A extends Object {}
console.log(A.__proto__ === Object); // true
console.log(A.prototype.__proto__ === Object.prototype);

A继承Object,A的prototype 指向父类Object. A的 prototype.proto 指向父类Object的prototype

  • 2
1
2
3
class Cat {}
console.log(Cat.__proto__ === Function.prototype); //true
console.log(Cat.prototype.__proto__ === Object.prototype); //true

由于Cat不存在任何继承,就相当于一个普通函数,由于函数都是Function 的实例,所以 Cat.proto指向 Function.prototype. 第二条继承链指向父类(Function.prototype) 的prototype属性,所以 Cat.prototype.proto === Object.prototype. Cat调用后会返回Object实例,所以 A.prototype.proto 指向构造函数(Object)的prototype

  • 3
1
2
3
class Cat extends null {};
console.log(Cat.__proto__ === Function.prototype); // true;
console.log(Cat.prototype.__proto__ === null); //true

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


文章作者: HKmaster
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 HKmaster !
评论
  目录