Appearance
原型(Prototype)和原型链(proto)
01.原型的概念
所创建的每一个函数,解析器(JS引擎) 都会向函数中添加一个属性prototype
,这个属性对应着一个对象,这个对象就是我们所谓的原型对象
,也叫显式原型,原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象。因此我们可以将对象中共有的内容,统一设置到原型对象中。
函数作为普通函数调用prototype
没有任何作用,当函数以构造函数
的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,可以通过__proto__(隐式原型)
来访问该属性。
当访问对象的一个属性
或方法
时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。
每一个对象的属性不一样这是一定的,但是它的方法似乎好像是一样的,如果我创建1000个对象,那岂不是内存中就有1000个相同的方法,那要是有10000个,那对内存的浪费可不是一点半点的,我们有没有什么好的办法解决,没错,我们可以把函数抽取出来,作为全局函数,在构造函数中直接引用就可以。上代码:
javascript
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
// 设置对象的方法
this.sayName = sayName
}
// 抽取方法为全局函数
function sayName() {
console.log(this.name);
}
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);
person1.sayName();
person2.sayName();
person3.sayName();
但是,在全局作用域中定义函数却不是一个好的办法,为什么呢?因为,如果要是涉及到多人协作开发一个项目,别人也有可能叫sayName这个方法,这样在工程合并的时候就会导致一系列的问题,污染全局作用域,那该怎么办呢?有没有一种方法,我只在Person这个类的全局对象中添加一个函数,然后在类中引用?答案肯定是有的,这就需要原型对象了,我们先看看怎么做的,然后在详细讲解原型对象
javascript
// 使用构造函数来创建对象
function Person(name, age) {
// 设置对象的属性
this.name = name;
this.age = age;
}
// 在Person类的原型对象中添加方法
Person.prototype.sayName = function() {
console.log(this.name);
};
var person1 = new Person("孙悟空", 18);
var person2 = new Person("猪八戒", 19);
var person3 = new Person("沙和尚", 20);
person1.sayName();
person2.sayName();
person3.sayName();
02.原型链的概念
先在自身属性中查找,找到返回,如果没有,再沿着__proto__
这条链向上查找,找到返回,如果最终没找到,返回undefined,这就是原型链,又称隐式原型链
,它的作用就是查找对象的属性(方法)。
javascript
Object对象是所有对象的祖宗,Object的原型对象指向为null,也就是没有原型对象