原型和原型链

吐槽君 分类:javascript

原型

先给出prototype和__proto__ 的结论:
1、 所有引用类型(函数,数组,对象)都拥有__proto__属性,并且指向它的原型对象。
2、 每个函数对象都有一个prototype原型对象。
3、 prototype原型对象里的constructor指向构造函数本身。
我们来证明一下:

image.png

我们定义了一个对象obj和数组arr,并将它们打印出来发现它们都有__proto__属性,从而证实了结论1。

image.png

此外,还定义了一个函数fn,通过打印可以看到fn除了有__proto__属性以外,还有一个prototype属性。

prototype和__proto__的作用?
实例对象的__proto__指向构造函数的prototype,从而实现继承。
prototype对象相当于特定类型所有实例对象可以访问的公共容器。
我们来看一个例子吧:

function Person(nick, age){
    this.nick = nick;
    this.age = age;
}
Person.prototype.sayName = function(){
    console.log(this.nick);
}
var p1 = new Person('Byron', 20);
var p2 = new Person('Casper', 25);
p1.sayName()  // Byron
p2.sayName()  // Casper
p1.__proto__ === Person.prototype       //true
p2.__proto__ === Person.prototype   //true
p1.__proto__ === p2.__proto__           //true
Person.prototype.constructor === Person  //true
 

图示如下:

image.png
这里我们需要知道new做了什么

  • 自动创建了空对象
  • 自动为空对象关联原型,原型地址指向Person.prototype
  • 自动将空对象作为this关键字运行构造函数
  • 自动return this

关于构造函数Person

  • Person函数本身负责给对象本身添加属性
  • Person.prototype对象负责保存对象的公共属性

原型链

每个对象都有一个__proto__,它指向它的prototype原型对象,而prototy原型对象也具有一个自己的prototype原型对象,这样层层往上直到一个对象的原型prototype为null,这个查询路径就是原型链。
我们还是来举例子吧:看以下代码:

var arr = [1,2,3]
arr.valueOf()
 

再看图:

image.png
可以看出,arr的自身并没有valueOf的方法,arr.__proto__上也没有valueOf()的方法,那它是从哪里来的?看下图:

image.png

最终,在Array.prototype.__ proto__ 里找到valueOf方法。
查找valueOf大概的过程:
1、当前实例对象的obj,查找obj的属性或方法,找到后返回。
2、没有找到,通过obj.__ proto __,找到obj构造函数的prototype并且查找上面的属性和方法,找到后返回。
3、没有找到,把Array.prototype当作obj,重复以上步骤。

当然不会一直找下去,原型链是有终点的,最后找到Object.prototype时,Object.prototype.__ proto __ === null,意为着查找结束。
原型链如下:
arr —> Array.prototype —> Object.prototype —> null

实现继承

通过原型链可以实现继承:

function Animal(color){
	this.color=color
}
Animal.prototype.say=function(){} //动物可以叫

function Dog(color,name){
	Animal.call(this,color)
    this.name=name
}
// 以下将Dog.prototype.__proto__=Animal.prototype
function temp(){}
temp.prototype=Animal.prototype
Dog.prototype=new temp()

Dog.prototype.constructor=Dog
Dog.prototype.say=function(){consolr.log('汪汪')}

var dog=new Dog('白色','小花')
console.log(dog) //Dog {color: "白色", name: "小花"}
 

3个定理

1、对象.proto===其构造函数.prototype

image.png

2、Object.prototype是所有对象的(直接或间接原型)

image.png 3、所有函数都是由Function构造的,任何函数.proto===Function.prototype,任何函数包含(Object、Array、Function)

image.png

参考链接:
juejin.cn/post/688663…
zhuanlan.zhihu.com/p/35790971
www.jianshu.com/p/dee9f8b14…

回复

我来回复
  • 暂无回复内容