javascript对象详解:__proto__和prototype的区分和联络

媒介

本篇文章用来纪录下近来研讨对象的一些心得,做一个纪录与总结,以加深本身的印象,同时,愿望也能给正在进修中的你一点启示。本文合适有肯定JavaScript基本的童鞋浏览。原文戳这里

弁言

在JavaScript中,万物皆对象。我们写一个JavaScript对象,大多数时刻是用组织函数建立一个对象或许用对象字面量建立一个对象。比方:

//经由过程组织函数来建立对象
function Person() {
    //...
}

var person1 = new Person();

//经由过程对象字面量建立对象
var person2 = {
    name: 'jessica',
    age: 27,
    job: 'teacher'
}

固然另有其他体式格局建立对象,这里就不枚举出来了。那末题目来了,经由过程差别的体式格局建立的对象有什么区分呢?

我们晓得,每一个JS对象肯定对应一个原型对象,并从原型对象继续属性和要领。那末对象是怎样和这个原型对象对应的呢?带着题目逐步看下面的内容吧~

__proto__prototype观点辨别

实在说__proto__并不正确,确实的说是对象的[[prototype]]属性,只不过在主流的浏览器中,都用__proto__来代表[[prototype]]属性,由于[[prototype]]只是一个规范,而针对这个规范,差别的浏览器有差别的完成体式格局。在ES5顶用Object.getPrototypeOf函数取得一个对象的[[prototype]]。ES6中,运用Object.setPrototypeOf能够直接修正一个对象的[[prototype]]。为了轻易,我下面的文章用__proto__来代表对象的[[prototype]]

prototype属性是只要函数才特有的属性,当你建立一个函数时,js会自动为这个函数加上prototype属性,值是一个空对象。所以,函数在js中是异常特别的,是所谓的一等国民
那末__proto__prototype是怎样联络起来的呢?让我们来看下下面的代码:

function Person(name, age) {
    this.name = name;
    this.age = age;
}

var person1 = new Person('jessica', 27);

当我们new Person()的时刻终究发生了什么?

new一个组织函数,相当于实例化一个对象,这时期实在进行了这三个步骤:

  1. 建立对象,设为o,即: var o = {};

  2. 上文提到了,每一个对象都有__proto__属性,该属性指向一个对象,这里,将o对象的__Proto__指向组织函数Person的原型对象(Person.prototype);

  3. o作为this去挪用组织函数Person,从而设置o的属性和要领并初始化。

当这3步完成,这个o对象就与组织函数Person再无联络,这个时刻纵然组织函数Person再加任何成员,都不再影响已实例化的o对象了。
此时,o对象具有了nameage属性,同时具有了组织函数Person的原型对象的一切成员,固然,此时该原型对象是没有成员的。

如今人人都邃晓了吧,简朴的总结下就是:

js在建立对象的时刻,都有一个叫做__proto__的内置属性,用于指向建立它的函数对象的原型对象prototype

那末一个对象的__proto__属性终究怎样决议呢?答案不言而喻了:是由组织该对象的要领决议的。

建立对象的差别要领剖析

下面解说三种罕见的建立对象要领。

对象字面量

比方:

var Person = {
    name: 'jessica',
    age: 27
}

这类情势就是对象字面量,经由过程对象字面量组织出的对象,其__proto__指向Object.prototype

所以,实在Object是一个函数也不难明白了。Object、Function都是是js自带的函数对象。

能够跑下面的代码看看:

console.log(typeof Object); 
console.log(typeof Function); 

组织函数

就如我前面讲的,形如:

function Person(){}
var person1 = new Person();

这类情势建立对象的体式格局就是经由过程组织函数建立对象,这里的组织函数是Person函数。上面也讲过了,经由过程组织函数建立的对象,其__proto指向的是组织函数的prototype属性指向的对象。

Object.create

var person1 = {
    name: 'jessica',
    age: 27
}
var person2 = Object.create(person1);

这类情况下,person2__proto__指向person1。在没有Object.create函数的时刻,人们大多是如许做的:

Object.create = function(p) {
    function f(){};
    f.prototype = p;
    return new f();
}

一看人人就会邃晓了。

总结

实在细致思索下上面提到的三种建立对象的要领,追查其本质,不难发明,最基础的照样应用组织函数再经由过程new来建立对象。所谓的对象字面量也只不过是语法糖罢了,本质上是var o = new Object(); o.xx = xx;o.yy=yy;。 所以,函数真不愧是js中的一等国民呀~

原型链

既然已提到了原型,就不得不提一下原型链了,毕竟这是完成继续最关键地点,也是js对象精巧地点。

还记得上文提到的一个总结吗?不记得?没紧要,我贴出来让人人温故而知新,哈哈~

js在建立对象的时刻,都有一个叫做__proto__的内置属性,用于指向建立它的函数对象的原型对象prototype

而原型链的基本思想就是应用原型让一个援用范例继续另一个援用范例的属性和要领。

让我们再简朴回忆下组织函数、原型和实例的关联:

每一个组织函数都有一个原型对象,原型对象包括一个指向组织函数的指针(constructor),而实例则包括一个指向原型对象的内部指针(__proto__)。

我们拿一个例子来解说:

function Person(name, age) {
    this.name = name;
    this.age = age;
}

var person1 = new Person('jessica', 27);

一图胜媒介,我们用绘图的情势来解说下上面的例子:

《javascript对象详解:__proto__和prototype的区分和联络》

从上图能够看到,实在原型链的顶端是Object.prototype.__proto__,也即为null

总结

函数是js中的一等国民,js在建立对象的时刻,都有一个叫做__proto__的内置属性,用于指向建立它的函数对象的原型对象prototype。只要函数有prototype, 当你建立一个函数时,js会自动为这个函数加上prototype属性,值是一个空对象。

参考文献

js 对象、原型、继续详解
js中__proto__和prototype的区分和关联?
明白JavaScript原型

    原文作者:mengera88
    原文地址: https://segmentfault.com/a/1190000009704212
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞