原型与原型链

252 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

概念

原型 prototype 原型链 __proto__ [[Prototype]] image.png

原型

思考一个问题🤔

普通的对象或者数组上有原型吗?我们试一试 原型上是可以定义属性或者变量的。我们向obj上添加 a = 666。

 let obj = {}
 let arr = []
 obj.prototype.a = 666;

控制台会发生报错。 image.png 所以,也就是说对象或者数组上没有原型

原型是函数特有的

 function fn(){

    }
 fn.prototype.name = '第一个'
  // 赋值的过程不需要给函数加括号 声明才需要()
 fn.prototype.fn2 = function(){
        console.log('添加函数')
  }
 console.dir(fn.prototype)

image.png 那么原型有什么用呢?原型用于继承。

引出原型链

我们为Person()函数的原型上,添加变量name、age 和 方法 getAge()

 function Person(){

    }
   Person.prototype.name = '张三'
   Person.prototype.age = 18
   Person.prototype.getAge = function(){
           console.log(this.age)
   }

然后实例化一个person1,调用它原型上的 getAge()。【当使用Person()去构造一个新函数时,Person()才是一个构造函数】

let person1 = new Person()
person1.getAge()          // 此时会打印出 18

有一个问题🤔,如果我在调用getAge()前 改变了 person1的age。那输出的会是什么呢?

let person1 = new Person()
person1.age = 28
person1.getAge()     // 此时输出 28

有人会说这是一个就近原则。其实这就引出了原型链。这是在因为在原型链上离得较近。

原型链

原型链查找规则

从当前实例属性去查找,如果找到了就返回,否则顺着原型链一层一层的往上找。直到找到null为止。如果仍旧没找到就会报错。

我们打印一下person1,可以看到其自身就有age,所以他不会去其原型[[Prototype]]上去寻找age了

      function Person(){

            }
            Person.prototype.name = '张三'
            Person.prototype.age = 18
            Person.prototype.getAge = function(){
                console.log(this.age)
            }
            // 在使用Person()构造新的函数时 才可以叫做构造函数  person1 是一个实例
            let person1 = new Person()
            person1.age = 28
            person1.getAge()     // 此时就是28
            console.log(person1)

这是谷歌浏览器 image.png 我们在看一下火狐 其原型是 __proto__ image.png

我们再试一下,原型链上没有findd()方法。我们打印它看一下结果

 console.log(person1.findd())

如下会报错。 image.png

再试一下变量

    console.log(person1.abc)

只是会undefined

image.png

hasOwnProperty

我们想要看这个属性是它自身的还是原型链上的,怎么办呢?这就可以用到hasOwnProperty

 for(let item in person1){
         if(person1.hasOwnProperty(item)){
               console.log(item)
         }
   }

image.png

流程图

最后上一张沿着原型链寻找age和hasOwnProperty的图

image.png