最近面试了好多小伙伴,发现现在有一个奇怪的现象。好多小伙伴都是只会用vue进行业务开发,对于js的基础知识都停留在知道有这个东西的层面上。我觉得大家还是需要将基础夯实,这样才能在后面走的更远。
今天准备就我对原型和原型链的理解给大家分享一波,如果有不对的地方,欢迎大家指出。
本文核心知识点
- prototype
- [[proto]] 备注:部分浏览器实现为__proto__
JavaScript 设计规则
1. Object(对象)有__proto__属性
2. Function(函数)有prototype属性
3. 对象都是由函数生成的,而函数又是一种对象
4. 所有对象生成时,对象的__proto__都会指向Function(函数)的prototype属性
所有原型链的前提都是根据上面几个规则来的
对于上面基础原则,代码展示
var a = {}
a.prototype // undefined
var b = function(){}
b.__proto__ // ƒ () { [native code] }
b.prototype // {constructor: ƒ}
一、 最简单的情况
// 构造函数 Foo
var Foo = function(){}
// 实例化构造函数
var foo = new Foo()
foo.__proto__ === Foo.prototype
Foo.__proto__ === Function.prototype
Foo.prototype.constructor === Foo
Foo.prototype.__proto__ === Object.prototype
// typeof Foo.prototype Object 原型对象
这里我们定义了构造函数 Foo,并且实例化了一个 foo,对于foo的__proto__属性,指向了构造函数的prototype属性,即指向Foo的prototype。
对于构造函数Foo,他也是一个函数,Foo的__proto__属性则指向了Function的prototype属性。
对于Foo的prototype,和所有function一样,函数的prototype的constructor指向函数本身。
函数的原型都是对象,所以称为原型对象,所以Foo.prototype的__proto__属性指向了Object的原型
二、核心部分 Function 和 Object 的关系
Function.__proto === Function.prototype // true
Object.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__ === null // true
因为上面部分都是 true ,就会有一个神奇的 现象
Function instanceof Function // true
Object instanceof Object // true
Function instanceof Object // true
Object instanceof Function // true
Function的__proto__指向Function的prototype属性,是因为Function也是通过Function生成的,即函数也是通过函数实例化出来的,所以Function的原型链指向他的原型对象
Object的__proto__指向Function的prototype属性,也是因为Object是通过函数生成的,所以Object的__proto__指向了Function的prototype
Function的prototype属性的__proto__,指向Object的prototype,是因为所有原型都是对象,对象的__proto__属性,则都指向了Object的prototype属性
Object的原型对象的__proto__,往上找已经到顶了,即为null
根据上面的等式部分,推出了这个神奇的instance等式。Function和Object互相以及和自己都在自己原型链上
三、理解上面部分,做几个题目试试吧
- 题目1
var Foo = function() {}; Foo.prototype.n = 1; var foo1 = new Foo(); Foo.prototype = { n: 2, m: 3 } var foo2 = new Foo(); console.log(foo1.n); console.log(foo1.m); console.log(foo2.n); console.log(foo2.m);
解析:这一题目还涉及了一个引用类型的问题(注意这里修改Foo的prototype后,原来的prototype,还是在内存中的,这里实例化的对象存的是一个指向这里的地址,所以foo1的内容不会受打影响)
答案:
1
undefined
2
3
- 题目2
var obj = {},
Fun = function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';
console.log(obj.a);
console.log(obj.b);
console.log(Fun.a);
console.log(Fun.b);
解析
obj.__proto__ === Object.prototype
Object,prototype.__proto__ === null
Fun.__proto__ === Function.prototype
Function.prototype.__proto__ === Object.prototype
// 答案
value a
undefined
value a
value b
四、总结
第一部分我们就分析了原型和原型链最基础的相关知识,大家对于这部分最基础的掌握,才能对后面基于这块实现的js设计模式中的继承以及new的过程中做了哪些事情等等一系列知识进行学习。希望大家一起努力一起进步。