持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
前言
js中要说比较让人难理解的技术点,我想原型与原型链可以算其中一个比较难理解的知识点。我们得理解隐式原型、显示原型、new关键字、构造函数等等概念要熟悉。
什么是原型
在JavaScript中,每个对象都有一个内置的属性prototype,这个属性也是一个对象,并且指向另外一个对象,这个属性prototype就可以叫做对象的原型。
首先我们得先理解几个关键属性
__proto__
这个属性叫隐式原型,可以通过 对象. _proto_获取到,不过这个是浏览器自己添加的,存在一定的兼容性问题,所以实际代码里如果要使用这个属性,一般要做判断,但是不建议直接拿来用。
var proObj ={
name:'gogo',
age:23
}
console.log(proObj)
console.log(proObj.__proto__)
如果想要拿对象的原型,建议通过
Object.getPrototypeOf(proObj)来获取到这个对象的原型。因此可以得出
Object.getPrototypeOf(proObj) == proObj.__proto__
prototype
这个属性叫显示原型,只有函数对象才有,也就是所有的函数都有prototype属性。
function Person(){
name:'person'
}
console.log(Person.prototype)
console.log(Person.__proto__)
new 操作符
new 操作的过程是
创建一个空对象,将这个空对象赋值给this。
将函数的显示原型赋值给这个对象作为它的隐式原型
执行函数体代码,将这个对象默认返回。
var o1=new Person()
console.log(o1.__proto__)
console.log(Person.prototype)
执行代码看下结果,可以看到2个是相等的。
原型链
从一个对象上获取属性,如果在当前对象没有获取到就会去它的原型上获取。
function Animal(name) {
this.name = name;
}
//如果没有dance方法,就去构造函数原型对象prototype身上去查找dance这个方法。
Animal.prototype.dance = function () {
console.log(this.name + '2');
};
//如果再没有dance方法,就去Object原型对象prototype身上去查找dance这个方法。
Animal.prototype.dance = function () {
console.log(this.name + '3');
};
//如果再没有,则会报错。
let obj = new Animal('小狗');
obj.dance();
console.log(obj)
console.log(obj.__proto__); //{dance: ƒ, constructor: ƒ}
我们调用了对象的方法,发现并没有,因此会去对象Animal上的原型去查找,我们在这个原型上定义了这个方法,因此会调用到这个方法。
如果在Animal的原型上没有找到dance方法,那么就会继续找上层原型,即原型对象的原型,写法如下, 发现在继续向上找,就找到了Object原型,并且存在这个方法,因此完成这次操作,这就是原型链的操作。
console.log(obj.__proto__); //{ constructor: ƒ}
console.log(obj.__proto__.__proto__); //
总结
某个函数作为对象都是Function的实例对象,因此也存在隐式原型,指向Function的显示原型。
某个函数作为函数存在,则存在显示原型和隐式原型,显示原型则指向本身函数对象的原型。
Person.prototype.__proto__==Object.prototype
某个Object对象则只有隐式原型,指向Object的显示原型。
整个原型的规则思路则是按下图,理解完这个图,则掌握