原型、构造函数、实例、原型链的关系

一、概要

  • 本文主要介绍了原型链的相关知识
  • 建立对象的方法
  • 原型、构造函数、实例、原型链的关系
  • 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. 总结

  1. 本身也是在处在深刻学习和理解的阶段,若有错误之处,请指正。
  2. 后续为将继续分享继承以及面向对象的相关内容。
  3. 未完待续。
相关文章
相关标签/搜索