概念
原型 prototype 原型链 __proto__ [[Prototype]]
普通的对象或者数组上有原型吗?我们试一试 原型上是可以定义属性或者变量的。我们向obj上添加 a = 666。
let obj = {}
let arr = []
obj.prototype.a = 666;
控制台会发生报错。
所以,也就是说对象或者数组上没有原型
function fn(){
}
fn.prototype.name = '第一个'
// 赋值的过程不需要给函数加括号 声明才需要()
fn.prototype.fn2 = function(){
console.log('添加函数')
}
console.dir(fn.prototype)
那么原型有什么用呢?原型用于继承。
我们为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)
这是谷歌浏览器
我们在看一下火狐 其原型是 __proto__
我们再试一下,原型链上没有findd()方法。我们打印它看一下结果
console.log(person1.findd())
如下会报错。
再试一下变量
console.log(person1.abc)
只是会undefined
我们想要看这个属性是它自身的还是原型链上的,怎么办呢?这就可以用到hasOwnProperty
for(let item in person1){
if(person1.hasOwnProperty(item)){
console.log(item)
}
}
最后上一张沿着原型链寻找age和hasOwnProperty的图