JS原型链原理分析研究

原型和原型链是什么?

原型: 所谓的原型就是一个对象,可以称为原型对象。它是构造函数的prototype指向的对象或是通过构造函数创建的实例对象的__proto__指向的对象等,原型对象是用于给所有实例对象提供共有属性和方法的对象。
原型链: 所谓的原型链是一条通过对象的__proto__属性组成的一条搜索机制。原型链的根是Object.prototype,而这个对象的__proto__是null,所以基于原型链的搜索机制如果到此都无法找到则返回null,代表没有找到。
js基础: JS中一切皆对象,所以在JS中函数也是对象,但函数对象和普通对象还是有一些区别,就是函数对象具有__proto__和prototype两个属性,而普通对象只具有__proto__属性。

先上一张图,一图胜千言万语
在这里插入图片描述
从图中可以很清晰的知道__proto__具体指向谁,像通过构造函数创建的对象它的__proto__指向的是构造函数的prototype对象,通过字面量创建的对象,它的__proto__指向的是Object.prototype对象,通过Object.create()方法创建的新对象,新对象的__proto__指向的是传入的对象。

代码解析

  • 自定义构造函数对象
    function Obj() {}
    var obj = new Obj();
    console.log(obj.__proto__ == Obj.prototype); //true
    console.log(Obj.__proto__ == Function.prototype); //true
    console.log(Obj.__proto__ == Object.prototype); //false
    console.log(Obj.prototype == Function.prototype); //false
    console.log(Obj.prototype.__proto__ == Function.prototype); //false
    console.log(Obj.prototype.__proto__ == Object.prototype); //true
    console.log(Obj.prototype.constructor == Obj); //true
    console.log(Obj.prototype.__proto__.__proto__); //null

当我们自定义构造函数时,JS会为我们创建Obj的prototype对象,当我们通过new创建obj对象时,JS会把obj对象的__proto__指向Obj.prototype对象。obj对象在使用属性和方法时,首先会先在自身查找,如果没有找到再到Obj.prototype对象上查找,如果还是没有找到再到Object.prototype对象上找,要是还没找到则就说明没有这个属性或方法而报错,因为Object.prototype.__proto__返回为null。

  • 字面量对象
	var obj = {}
	console.log(obj.prototype); //undefined
	console.log(obj.__proto__ == Object.prototype); //true  指向原型链的顶层对象Object.prototype
    console.log(obj.__proto__ == Function.prototype); //false

obj.prototype为undefined,说明对象是没有prototype属性的,只有函数才具有prototype属性,而第二个打印出true,说明字面量对象是Object构造函数的实例,而不是Function的实例。

  • 通过Object创建的对象
    var obj = new Object();
    console.log(obj.__proto__ == Object.prototype); //true
    console.log(Object.__proto__ == Function.prototype); //true
    console.log(Object.prototype == Function.prototype); //false
    console.log(Object.prototype == Object.prototype); //true
    console.log(Object.prototype.constructor == Object); //true
    console.log(Object.constructor ==Function); //true
    console.log(Object.constructor ==Object); //false

通过Object创建的对象和字面量创建的对象其实是一样的,

  • 通过Function构造函数创建对象
	  var fun = new Function();
      console.log(fun.__proto__ == Function.prototype); //true
      console.log(Function.__proto__ == Function.prototype); //true
      console.log(Function.prototype.__proto__ == Object.prototype); //true
      console.log(Function.prototype.constructor == Function); //true
      console.log(Function.constructor == Function); //true
      console.log(Function.constructor == Object); //false

所有的内置构造函数都是通过Function构造出来的,包括Function构造函数,所以Function的__proto__和prototype都指向了Function.prototype,而Function.prototype比较特殊他是一个函数,但它又没有prototype属性。

  • 通过Array构造函数创建对象
	var arr = new Array();
    console.log(arr.__proto__ == Array.prototype); //true
    console.log(Array.__proto__ == Function.prototype); //true
    console.log(Array.prototype == Function.prototype); //false
    console.log(Array.prototype.__proto__ == Function.prototype); //false
    console.log(Array.prototype.__proto__ == Object.prototype); //true
    console.log(Array.prototype.constructor == Array); //true

因为所有的内置构造函数都是通过Function构造出来的,所以Array的__proto__指向了Function.prototype,而对象又都指向它构造函数的prototype,所以arr.__proto__指向了Array.prototype。

  • 通过Object.create传入构造函数对象
	 function Foo() {}
     var newObj = Object.create(Foo);
     console.log(newObj.__proto__ == Foo); //true
     console.log(newObj.__proto__.prototype == Foo.prototype); //true
     console.log(newObj.__proto__.__proto__ == Function.prototype); //true

通过Object.create创建的对象的__proto__都是指向传入的对象,所以newObj.__proto__指向了Foo,而此时再往上查找就不是查找Foo.prototype了,而是查找Foo.proto,而Foo.__proto__指向了Function.prototype,因为所有的函数都是Function的实例

  • 通过Object.create传入字面量对象
    var obj= {};
    var newObj = Object.create(obj);
    console.log(newObj.__proto__ == obj); //true
    console.log(newObj.__proto__.prototype); //undefined,对象没有此属性
    console.log(newObj.__proto__.__proto__ == Object.prototype); //true
    console.log(newObj.__proto__ == Object.prototype); //false

和传入构造函数对象差不多,只是原型链的查找不一样,newObj如果在自身没有找到,就会去obj查找,还是没找到就会去Object.prototype上查找,要是再没有就报错。因为字面量对象是由Object构造函数创建的,所以obj的__proto__指向Object构造函数的prototype属性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值