关于原型和原型链的区别,秉着晚学不如早学的原则,今天特意进行对这个知识点进行了梳理。
原型主要优点
- 能实现数据共享节约内存空间
- 实现继承机制
一、new运算符的缺点
function Person(name) {
this.name=name;
this.eat= function(){
console.log(this.name+"吃东西");
}
this.sleep=function() {
console.log(this.name+"睡觉");
}
}
var person1=new Person("小王");
person1.eat();//小王吃东西
person1.sleep();//小王睡觉
var person2=new Person("小熊");
person2.eat();//小熊吃东西
person2.sleep();//小熊睡觉
console.dir(person1)
console.dir(person2)
在上面的这段代码中,每一个实例对象,都有自己的属性和方法的副本。这不仅无法做到数据共享,也是极大的资源浪费。所以网景公司的工程师Brendan Eich,考虑到这一点决定为构造函数设置一个prototype属性。
二、prototype(原型)属性的引入
function Person(name) {
this.name=name;
}
Person.prototype.eat =function(){
console.log(this.name+"吃东西");
}
Person.prototype.sleep =function(){
console.log(this.name+"睡觉");
}
var person1=new Person("小王");
person1.eat();//小王吃东西
person1.sleep();//小王睡觉
var person2=new Person("小熊");
person2.eat();//小熊吃东西
person2.sleep();//小熊睡觉
console.dir(person1)
console.dir(person2)
在我们把eat()和sleep()方法添加到Person对象的prototype(原型)
上之后,在new出来的实例perosn1和person2他们就是公用原型上的方法,这样就很好的做到了数据共享,节约了内存资源。Person()构造函数的prototype(原型)
属性是一个对象,person1实例的__proto__
也是一个对象,之所以在prototype(原型)
上定义的方法能在实例上使用也就是因为这两者的指向相同,都是指向同一个地址。
三、啥是原型链?
图画的搓了点,希望大家别介意。上面就是我想表达的原型链,通过__proto__
属性一层层往上找,最终null,也就是说在原型链上的所有方法我们都是可以使用。换个方法来说也就是如果需要有一个方法被所有实例调用,那么就可以直接定义在Object
// 在Obejct 原型上定义一个clogname函数
Object.prototype.clogname = ()=>{
console.log("玩转js原理!");
}
// 创建一个str字符串,对象可以通过__proto__来访问原型中的方法
let str= 'xxx'
str.__proto__ == String.prototype // true
str.__proto__.__proto__.clogname() // 输出 "玩转js原理!" ,因为str.__proto__.__proto__ 等价于 Object.prototype
console.log(str.__proto__.__proto__.__proto__); // 输出 "null" ,因为str.__proto__.__proto__.__proto__ 等价于 Object.__proto__,而Object.__proto__是最顶层了没有原型所以null
//总结:__proto__指向该对象所在的构造函数的原型对象,链式调用最终一定会返回最顶层null。
以上就是我对原型和原型链的理解,如果文章由于我学识浅薄,导致您发现有严重谬误的地方,请一定在评论中指出,我会在第一时间修正我的文章,以避免误人子弟。