【JavaScript高级】原型与原型链

原型与原型链一直是JavaScript的重难点,掌握这部份内容将会使咱们的工做更加的高效,并且这也是面试官必问的内容。javascript

首先,咱们要明确的是,在 ES6 以前,咱们建立一个实例并非经过类(class),而是直接使用构造函数来实现的。java

1、构造函数

经过 new 函数名 来实例化对象的函数叫构造函数。任何的函数均可以做为构造函数存在。构造函数首字母通常大写。面试

那么,咱们使用构造函数来建立一个对象。浏览器

function Person(name , age , sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
}
var person = new Person("Tony" , 18 , "男");
console.log(person.name);  // Tony
复制代码

上面这段代码就是建立一个了Person 的构造函数,在Person 构造函数中,为每个对象都添加了三个属性(name,age,sex),也就是说构造函数每执行一次就会建立一个新的Person对象。markdown

构造函数简单复习一下,下面步入正题。函数

2、原型

prototype

在JS中,每当定义一个函数时候,都会默认自带一个prototype属性,这个属性指向的是该构造函数建立的实例的原型,而且这个属性是一个对象数据类型的值。ui

原型:每个JS对象(null除外)在建立的时候就会与之关联另外一个对象,这个对象就是咱们所说的原型,每个对象都会从原型"继承"属性。this

举个原型的Demo:spa

function Person() { }
Person.prototype.name = 'Tony';  // 注意:prototype是函数才会有的属性
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);  // Tony
console.log(person2.name);  // Tony
复制代码

构造函数和实例原型之间的关系: 构造函数和实例原型之间的关系: 在这里 Person.prototype 表示实例原型。原型对象就至关于一个公共的区域,全部同一个类的实例均可以访问到这个原型对象,咱们能够将对象中共有的内容,统一设置到原型对象中。prototype

3、原型链

上面,咱们说明了实例和实例原型,那么咱们该怎么表示这二者之间的关系呢?这时候咱们就要说到下面两个属性了

__proto__

这是每个JS 对象(除了 null )都具备的一个属性,叫__proto__,这个属性会指向该对象的原型。

person.__proto__ === Person.prototype   // true
复制代码

__proto__ 绝大部分浏览器都支持这个非标准的方法访问原型,然而它并不存在于 Person.prototype 中,实际上,它是来自于 Object.prototype ,与其说是一个属性,不如说是一个 getter/setter,当使用 obj.__proto__ 时,能够理解成返回了 Object.getPrototypeOf(obj)

constructor

每一个原型都有一个 constructor 属性指向关联的构造函数。

Person === Person.prototype.constructor  // true
复制代码

当获取 person.constructor 时,其实 person 中并无 constructor 属性,当不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,因此:

person.constructor === Person.prototype.constructor
复制代码

实例原型与构造函数的关系图: 实例原型与构造函数的关系图 原型链:在JS中,万物皆对象,对象和对象之间也是有关系得,并非孤立存在的。对象之间的继承关系,在JS 中是经过prototype对象指向父类对象,直到指向Object对象为止,这样就造成了一个原型指向的链条,专业术语称之为原型链。

实例和原型

当咱们读取实例的一个属性或方法时,它会先在对象自身中寻找,若是有则直接使用,若是没有则会去原型对象中寻找,若是找到则直接使用。若是没有则去原型的原型中寻找,一直找到最顶层Object为止,Object对象的原型没有原型(Object是JS中全部对象数据类型的基类(最顶层的类)在Object.prototype上没有__proto__这个属性),若是在Object原型中依然没有找到,则返回undefined

function Person() {}
Person.prototype.name = 'Tony';
var person = new Person();

// 当咱们给实例对象person添加了name属性,打印 person.name 时,结果为name的值Ken。
person.name = 'Ken';
console.log(person.name) // Ken

// 当咱们删除了person的name属性时,再次读取person.name,从person 对象中找不到name属性就会从person的原型也就是person.__proto__和Person.prototype中查找name属性,由于以前咱们给他添加了,因此找到了 name属性为 Tony。
delete person.name;
console.log(person.name) // Tony
复制代码

咱们能够使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,若是自身属性存在,则返回 true,不然为false;使用in检查对象中是否含有某个属性时,若是对象中没有可是原型中有,则会返回true,若是都没有则返回false

function Person() {
    this.name = 'Tony'
}

Person.prototype.age = 18;

var person = new Person();

console.log(person.hasOwnProperty('name')); // true
console.log(person.hasOwnProperty('age'));  // false

console.log('name' in person);  // true
console.log('age' in person);   // true
console.log('a' in person);     // false
复制代码

最后,相互关联的原型组成的链状结构就是原型链,也就是蓝色的这条线: 在这里插入图片描述


用心读完上面的总结,应该会对 JS 的原型与原型链有了一个深层次的认识吧,其实这部分仍是须要细心琢磨的,毕竟是比较底层的原理。

相关文章
相关标签/搜索