资讯专栏INFORMATION COLUMN

javascript对象详解:__proto__和prototype的区别和联系

chavesgu / 3279人阅读

摘要:当这步完成,这个对象就与构造函数再无联系,这个时候即使构造函数再加任何成员,都不再影响已经实例化的对象了。此时,对象具有了和属性,同时具有了构造函数的原型对象的所有成员,当然,此时该原型对象是没有成员的。

前言

本篇文章用来记录下最近研究对象的一些心得,做一个记录与总结,以加深自己的印象,同时,希望也能给正在学习中的你一点启发。本文适合有一定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一个构造函数,相当于实例化一个对象,这期间其实进行了这三个步骤:

创建对象,设为o,即: var o = {};

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

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);

一图胜前言,我们用画图的形式来讲解下上面的例子:

从上图可以看到,其实原型链的顶端是Object.prototype.__proto__,也即为null

总结

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

参考文献

js 对象、原型、继承详解
js中__proto__和prototype的区别和关系?
理解JavaScript原型

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86999.html

相关文章

  • __proto__prototype之区别联系

    摘要:当这步完成,这个对象就与构造函数再无联系,这个时候即使构造函数再加任何成员,都不再影响已经实例化的对象了。此时,对象具有了和属性,同时具有了构造函数的原型对象的所有成员,当然,此时该原型对象是没有成员的。 学到原型的时候感觉头都大了/(ㄒoㄒ)/~~ 尤其是prototype和__proto__ 傻傻分不清,通过多番查找资料,根据自己的理解,记录下最近研究对象的一些心得,做一个记录与总...

    paulli3 评论0 收藏0
  • JavaScript学习总结(五)原型原型链详解

    摘要:原型对象内部也有一个指针属性指向构造函数实例可以访问原型对象上定义的属性和方法。在创建子类型的实例时,不能向超类型的构造函数中传递参数。 赞助我以写出更好的文章,give me a cup of coffee? 2017最新最全前端面试题 私有变量和函数 在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。 function ...

    EscapedDog 评论0 收藏0
  • js对象详解(JavaScript对象深度剖析,深度理解js对象)

    摘要:对象详解对象深度剖析,深度理解对象这算是酝酿很久的一篇文章了。用空构造函数设置类名每个对象都共享相同属性每个对象共享一个方法版本,省内存。 js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了。 JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕。 平时发的文章基本都是开发中遇到的问题和对...

    CatalpaFlat 评论0 收藏0
  • 【前端基础进阶】JS原型、原型链、对象详解

    摘要:二构造函数我们先复习一下构造函数的知识上面的例子中和都是的实例。这两个实例都有一个构造函数属性,该属性是一个指针指向。原型链其中是对象的实例。 一. 普通对象与函数对象 JavaScript 中,万物皆对象!但对象也是有区别的。分为普通对象和函数对象,Object 、Function 是 JS 自带的函数对象。下面举例说明 var o1 = {}; var o2 =new Objec...

    explorer_ddf 评论0 收藏0
  • 探索 proto & prototype 与继承之间关系

    摘要:而和的存在就是为了建立这种子类与父类间的联系。创建一个基本对象建立新对象与原型我把它理解为类之间的连接执行构造函数小结可以理解为类,也就是存储一类事物的基本信息。原型原型链和继承之间的关系。 原型 原型的背景 首先,你应该知道javascript是一门面向对象语言。 是对象,就具有继承性。 继承性,就是子类自动共享父类的数据结构和方法机制。 而prototype 和 __proto__...

    dockerclub 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<