Js原型链详解

2020-04-10

prototype是函数的属性,指向这个函数的原型对象
_proto_是对象的属性,指向生成该对象的构造函数的原型对象
constructor是对象的属性,指向生成该对象的构造函数

由于Js万物皆为对象的思想,函数其实也是一种对象,即函数对象,因此 函数也有_proto_,指向Function.prototype

从一个实例对象的_proto_指针出发,层层向上查找它的父级对象,就形成了实例与原型的链条。当访问一个对象的属性时,如果属性不存在,js就会顺着原型链向它的父级对象查找,直到找到该属性为止。原型链的顶端是null,原型链实现了继承。

函数表达式和函数声明同名时,表达式优先级更高

1
2
3
4
5
6
7
8
var F = function () { 
console.log (1);
};
function F() {
console.log (2);
}

F(); // 1

prototype重写后,不影响已经实例化了的对象

1
2
3
4
5
6
7
8
function F() {}
Foo.prototype = {name: 'Tom'};

var f = new F();
console.log(f.name); // Tom

Foo.prototype = {};
console.log(f.name); // Tom

综合题1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var F = function () { };
F.prototype.x = function () {
console.log(2)
};
Function.prototype.y = function () {
console.log(3)
};
Object.prototype.z = function () {
console.log(1)
};

let f = new F();
f.x(); // 2
f.y(); // 报错, undefined
f.z(); // 1

console.log(f.constructor.x === F.prototype.x); // false
console.log(f.constructor.prototype.x === F.prototype.x); // true
console.log(f.constructor.y === Function.prototype.y); // true
console.log(f.constructor.z === Object.prototype.z); // true

综合题2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function F() {
name = function () {
console.log (1);
};
return this;
}
F.name = function () {
console.log (2);
};
F.prototype.name = function () {
console.log (3);
};
var name = function () {
console.log (4);
};

F.name(); // 2
name(); // 4
F().name(); // 1
name(); // 1
new F.name(); // 2, 相当于 new (Foo.name())
new F().name(); // 3, 相当于 (new Foo()).name()
new new F().name(); // 3, 相当于 new ((new Foo()).name())