一、概要
- 本文主要介绍了原型链的相关知识
- 建立对象的方法
- 原型、构造函数、实例、原型链的关系
- instanceof的原理
- new运算符
二、建立对象的方法
// 建立对象的方式
// (1) 字面量
var obj1 = { name: 'obj1' };
var obj2 = new Object({ name: 'obj2' }); // 不是字面量,但结果和字面量等同
// (2) 构造函数
var Fn = function(name) {
this.name = name;
}
var obj3 = new Fn('obj3');
// (3) Object.create
var parentObj = { name: 'obj4'};
var obj4 = Object.create(parentObj);
复制代码
三、原型、构造函数、实例、原型链
// 原型、构造函数、实例、原型链的关系
// 一、实例 ==> 1. 对象就是一个实例,就有_proto_属性
// 2. 实例经过_proto_原型链找到prototype原型对象,prototype原型对象的属性被全部实例共享。
// 二、构造函数 ==> 1.能够经过new运算符生成一个实例。
// 2.任何函数均可以做为构造函数。
// 3.只要被new运算符使用过的函数就是一个构造函数
// 三、原型 ==> 1. 函数都有prototype属性,prototype属性的值就是一个初始化的原型对象。
// 2. 原型对象有个constructor和_proto_属性,constructor是一个构造函数。
// 3. Fn.prototype.constructor === Fn // constructor函数指向构造函数自己。经过constructor把原型对象和构造函数关联。
// 四、原型链 ==>1. 对象有_proto_属性(函数也是对象,因此函数也有_proto_属性)
// 2. 实例经过_proto_原型链找到prototype原型对象,若是找不到,则经过原型对象的_proto_继续往上找,一直到顶层。
// 五、关系:==> 1. Fn.prototype.constructor === Fn // 构造函数原型的constructor属性指向构造函数自己
// 2. obj3.__proto__.constructor === Fn
// 3. obj3.__proto__.constructor === Fn.prototype.constructor
// 4. obj3.__proto__ === Fn.prototype // 修改prototype的属性, __proto__也会修改,同理也是
复制代码
四、instanceof的原理
// instanceof ==> 1. 判断实例对象的__proto__和构造函数的prototype属性指向同一个引用地址
(并不能判断一个对象是否是一个构造函数直接生成的实例),
// 2. obj3 instanceof Fn // true
// 3. obj3 instanceof Object // true,因为 Fn instanceof Object === true
// 4. 如何准确判断一个对象是否是一个构造函数直接生成的实例对象(经过constructor):
// obj3.__proto__.constructor === Fn.prototype.constructor // true
// obj3.__proto__.constructor === Object.prototype.constructor // false
复制代码
五、new运算符
var obj3 = new Fn('obj3');
obj3实例对象在建立过程
1. new运算符会先建立一个新对象,它继承自Fn.prototype。
2. 构造函数Fn被执行,相应的参数会被传入,this会被指向这个新的实例。
3. 在不传参数时,new Fn等同于new Fn()
4. 若是Fn返回了一个对象,那么这个对象会取代new出来的对象。
5. 若是构造函数没有返回对象,那么new出来的对象就是最终的结果。
new运算符的工做原理,用代码模拟
var newTest = function(fn) {
var initObj = Object.create(fn.prototype);
var obj = fn.call(initObj);
if(typeof obj === 'object') {
return obj;
} else {
return initObj;
}
}
var Fn = function() {
// this.name = 'obj3', 最后newTest(Fn)返回的结果彻底等同。
return {
name: 'obj3';
}
}
newTest(Fn)
复制代码
6. 总结
- 本身也是在处在深刻学习和理解的阶段,若有错误之处,请指正。
- 后续为将继续分享继承以及面向对象的相关内容。
- 未完待续。