原型和原型链

如何理解原型和原型链

        原型说白了就是对象的父级,当对象在调用某方法的时候,如果对象本身并未定义该属性或方法,系统就会往对象的父级去找有没有对应的方法或属性。

        也就是往对象的__proto__或prototype对象去找,找不到的话接着往对象的__proto__或prototype对象的父级接着找,直到找到或者找不到为止,这就是原型链。

原型链的简单介绍

var arr=[1,2,3];
var obj={
    getName() {
        console.log("我想你")
    }
}
var obj1={
    getFun() {
        console.log("我爱你")
    }
}
arr.__proto__=obj;
obj.__proto__=obj1;
console.log(arr)
arr.getFun() //输出:我爱你

        例如在上面的代码中,在arr自身的属性中并不存在getFun()这个方法,但是我们在执行arr.getFun()之前,为arr对象重新指定了它的__proto__对象,将它的父级指向了obj对象,又将obj对象的父级指向了obj1对象。

       也就是说,现在arr的父级是obj,而obj的父级是obj1,父级所拥有的属性会被子级继承,因此,虽然arr自身并不存在getFun()方法,但它的父级的父级存在这个方法,所以可以继承到这个方法从而去使用它

        但是,因为我们修改了arr.__proto__,它的所有父级中不再有指向Array.prototype的了,所以现在的arr如果使用数组方法就会报错

arr.concat(2);//报错 Uncaught TypeError: arr.concat is not a function

         想要接着使用Array的属性方法的话,那就再将父级指向Array.prototype就行了

var arr=[1,2,3];
var obj={
    getName() {
        console.log("我想你")
    }
}
arr.__proto__=obj;
obj.__proto__=Array.prototype;
arr=arr.concat(2)
console.log(arr)

        现在就可以正常使用了 


实例化对象的原型指向谁

        像var arr=[...]、var obj={...}、var string="..."、var boolean=“...”......,arr、obj、string、boolean还有其他的这些都是对应类型的实例化对象。

        而实例对象的__proto__默认指向该对象所属类型的根元素的prototype,示例如下,咱们声明了一个string类型的变量str,因为普通类型直接打印出来是不会显示出它的其他属性的,所以就直接使用__proto__属性来看吧。

        看吧,str.__proto__跟String.prototype是不是看起来一样?那咱们对比一下不就知道了么

        返回值都为true,也就是说这两者是一样的。

        又例如数组的实例对象arr的__proto__指向的就是Array.prototype,而object实例对象的__proto__指向的是Object.prototype

        以此类推,实例对象的__proto__是不是就是都指向对应类型的prototype?

        那倒不是,构造函数实例化出来的对象的__proto__指向的就不是Function的prototype

        实际上,构造函数实例化出来的对象的__proto__指向的是构造函数的prototype

        构造函数实例化出来的对象的__proto__指向的是构造函数的原型prototype,而不是直接指向Object的prototype,但构造函数的__proto__就真的是指向Object的prototype对象了。


修改了实例对象的__proto__后会怎么样

        在未对实例对象obj的__proto__进行修改之前,obj.__proto__跟Object.prototype是相等的

        如果像上面这样给obj的__proto__重新指定了对象,那么它跟Object.prototype就不再相等了。

        但是,如果只对Object.prototype进行修改,那么 实例对象的__proto__和Object.prototype还是相等的

        简单来说就是prototype实际上还是比__proto__更大的。


怎么找出实例对象的构造函数

        至于构造函数,构造函数实例化出来的对象可以通过下面这个写法获取到对应的构造函数,简单说就是从实例对象身上去找到声明它这个变量的构造函数

实例对象.__proto__.constructor

        通过上述方式便可以获取到实例对象的构造函数了。


 __proto__的最终指向是哪里

      所有对象的最终__proto__都指向Object.prototype,除了Object.prototype自己

console.log(Array.prototype.__proto__===Object.prototype)//true
console.log(String.prototype.__proto__===Object.prototype)//true
console.log(Function.prototype.__proto__===Object.prototype)//true
console.log(Number.prototype.__proto__===Object.prototype)//true
console.log(String.prototype.__proto__===Object.prototype)//true
......
console.log(Object.prototype.__proto__===Object.prototype)//false Object的prototype对象的__proto__指向的是null,封顶了。

        Object.prototype.__proto__=null,也就是说到这里就封顶了


那些js自带的构造函数的__proto__指向谁

        这个我不知道,我只知道下面这些是全等的

			console.log(Object.__proto__===Number.__proto__)
			console.log(Object.__proto__===String.__proto__)
			console.log(Object.__proto__===Function.__proto__)
			console.log(Object.__proto__===Boolean.__proto__)
			......

注意,这里说的是js自带的构造函数的__proto__指向,不是咱们自己写的构造函数的__proto__指向

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值