在了解原型链之前我们先来看一个简单的栗子
var F = function() {}; Object.prototype.a = function() { console.log('a'); }; Function.prototype.b = function() { console.log('b'); } var f = new F(); f.a(); // a f.b();// f.b() is not function F.a(); // a F.b(); // b
可以看到 f.b()
返回的是 f.b() is not function
这是因为new 出来的实例是一个对象,只会继承 Object 原型上的方法,而不会继承 Function 原型上的方法,用一张图可以看出关系如下
所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
所有函数拥有prototype属性(显式原型)(仅限函数)
代码简单分析
var one = {x: 1}; var two = new Object(); one.__proto__ === Object.prototype // true two.__proto__ === Object.prototype // true one.toString === one.__proto__.toString // true
我们知道JS是单继承的,Object.prototype是原型链的顶端,所有对象从它继承了包括toString等等方法和属性。
这里有个鸡和蛋的问题
Object本身既然是构造函数,继承了Function.prototype;Function也是对象,继承了Object.prototype
// 控制台输出 Object instanceof Function // true Function instanceof Object // true Function本身就是函数,Function.__proto__是标准的内置对象Function.prototype Function.prototype.__proto__是标准的内置对象Object.prototype
- 1、Function.prototype和Function.__proto__都指向Function.prototype,这就是鸡和蛋的问题怎么出现的
- 2、Object.prototype.__proto__ === null,说明原型链到Object.prototype终止,也就是原型链的顶端
只要是对象,就会有原型,就会有__proto__
任意函数(因为函数本身也是对象),就是说 function xxx() {} 的原型(通过__proto__往上找)就是 Function.prototype (还没完),而普通对象(比如{},或者xxx.prototype)的原型(通过__proto__往上找)就是 Object.prototype,但是 Function.prototype 也有__proto__ , 并且 proto 还是指向 Object.prototype,因为 Object.prototype 才是所有人的爸爸
总结
1、所有的函数都同时拥有__proto__和protytpe属性 函数的__proto__指向自己的函数实现 函数的protytpe是一个对象 所以函数的prototype也有__proto__属性 指向Object.prototype
2、所有的JS对象都有一个prototype属性,指向它的原型对象。当试图访问一个对象的属性时,如果没有在该对象上找到,它还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾Object.prototype终止
题目
题目来源网络,看了上面分析,下面的题目能如若能分析出来,差不多对原型链有了基础掌握,剩下的在实际工作去挖掘它更深的意义
1、请写出下面编程的输出结果是什么?
var A = function() {}; A.prototype.n = 1; var b = new A(); A.prototype = { n: 2, m: 3 } var c = new A(); console.log(b.n); console.log(b.m); console.log(c.n); console.log(c.m);
2、请写出下面编程的输出结果是什么?
var F = function() {}; Object.prototype.a = function() { console.log('a'); }; Function.prototype.b = function() { console.log('b'); } var f = new F(); f.a(); console.log(f.b); F.a(); F.b();
3、请看下面 p.__proto__等于什么?
4、请看下面 Person.__proto__等于什么?
function Person(name) { this.name = name } let p = new Person('Tom');
5、请写出下面编程的输出结果是什么?
var foo = {}, F = function(){}; Object.prototype.a = 'value a'; Function.prototype.b = 'value b'; console.log(foo.a); console.log(foo.b); console.log(F.a); console.log(F.b);
答案
题目 1 答案:
b.n -> 1 b.m -> undefined; c.n -> 2; c.m -> 3;
题目 2 答案:
f.a() -> a f.b -> f.b is not a function F.a() -> a F.b() -> b
题目 3 答案
Person.prototype
题目 4 答案
Function.prototype
题目 5 答案
foo.a => value a foo.b => undefined F.a => value a F.b => value b