要认知蓝本链,绕不行constructor、prototype、__proto__这两个核心理念的习题,它的亲密关系如下表所示:
上面的图是两个最简单的蓝本链,先有两个简单的重新认识。上面将紧紧围绕上面3积和式一点一点对蓝本链解明,最终在来归纳到底甚么是蓝本链,大自然就明晰了。
2. Caz
再正式宣布步入主轴以后,先介绍两个习题
2.1 表达式第一类与一般第一类
JavaScript 中,天地万物皆第一类,但第一类也是有区别的。分成一般对象和表达式第一类,Object 、Function 是 JS 便携式的表达式第一类 。
表达式第一类//f1,f2,归根到底都是透过 new Function()的形式展开建立的 function f1(){};//console.log(typeof f1)==function var f2 = function(){};//上列 var f3 = new Function(str,console.log(str));//上列一般第一类var o1 = {}; // console.log(typeof o1) == object var o2 = new Object();//上列 var o3 = new f1();//上列简单的说,凡是使用 function 关键字或 Function 构造表达式建立的第一类都是表达式第一类,其他的都是一般第一类
2.2 两个专业术语
显式蓝本:prototype隐式蓝本:__ proto __蓝本第一类:每个表达式第一类都有两个prototype 属性,这个属性指向表达式的蓝本第一类3. prototype和contructor
prototype指向表达式的 蓝本第一类,只有表达式或者说表达式第一类才拥有该属性。contructor指向蓝本第一类的构造表达式。可能很多人对甚么是蓝本第一类比较迷惑,个人是按照上面的模版记得:蓝本第一类 = 构造表达式名.prototype
//Person.prototype就是蓝本第一类 function Person() {} Person.prototype = { name: Zaxlct, sayName: function() { } }3.1 prototype和contructor亲密关系
主要从三个纬度来分析:自定义的构造表达式(Person)、Object表达式、Function表达式
3.2 prototype建立时机
在定义表达式时自动添加的, 默认值是两个空Object第一类
//定义构造表达式 function Fn() { // 内部语句: this.prototype = {} }3.3 prototype作用
透过给 Person.prototype 设置属性和方法之后,Person 的实例都会继承相应的属性和方法,所有的实列例共享一份,不会开辟新的空间。prototype用来实现基于蓝本的继承与属性的共享4. proto
JS 在建立第一类(不论是一般第一类还是表达式第一类)的时候,都有两个叫做__proto__ 的内置属性,用于指向建立它的构造表达式的蓝本第一类。
由于js中是没有类的概念,而为了实现继承,透过 __ proto __ 将第一类和蓝本联系起来组成蓝本链,就可以让第一类访问到不属于自己的属性。
4.1 表达式和第一类的亲密关系
所有表达式都是Function的实例(包含Function),所有构造器都继承了Function.prototype的属性及方法。
4.2 蓝本第一类间的亲密关系
所有的蓝本第一类__proto__最终指向了Object.prototype(除了Object.prototype的__proto__之外)。
js蓝本链最终指向的是Object蓝本第一类
4.3 proto建立时机
第一类的__proto__属性: 建立第一类时自动添加的, 默认值为构造表达式的prototype属性值
function Fn() { } // 内部语句: this.__proto__ = Fn.prototype var fn = new Fn()4.4 归纳
当你new两个构造表达式的时候,建立两个表达式实例,那么 『 表达式实例.__ proto __ === 该构造表达式.prototype 』所有的表达式都是由Function构造出来的,那么 『被构造出来的其他表达式.__ proto __ === Function.prototype 』所有的构造表达式的蓝本第一类都是由Object构造出来的,那么 『所有的构造表达式.prototype.__ proto __ === Object.prototype 』5. 完整蓝本链结构图
6. 蓝本链的查找和内存表现
function Person() { this.test1 = function () { console.log(test1()) } }console.log(Person.prototype) Person.prototype.test2 = function () { console.log(test2()) } Object.prototype.test3 = function () { console.log(test3()) } const personObj = newPerson() personObj.test1()//test1 personObj.test2()//test2 personObj.test3()//test3对应到内存中的蓝本链如下表所示图: