资讯专栏INFORMATION COLUMN

为什么需要prototype

0xE7A38A / 1399人阅读

摘要:但要讲原型就必须讲构造函数,讲构造函数就必须讲对象。所以我们是无法容忍这么愚蠢的事情发生的,因此就有了构造函数,跟类有点相似,但我们这里不讨论类。

首先,上一篇文章详细分析了原型属性自身属性的区别,但为了让大家更明白一点,所以这里讲一下为什么需要原型。但要讲原型就必须讲构造函数,讲构造函数就必须讲对象。首先来看看对象

新建一个对象的方法: 1.new Object:

var newObj = new Object; newObj.name = "keti"; newObj.color = "red"; newObj.changeColor = function(color){ newObj.color = color; }

这种方法看上去很蠢,所以我们找到另一种方法:使用literal直接创建,看上去要优雅得多:

2.literal

var newObj = { name: "keti"; color: "red"; changeColor: function(color){ newObj.color = color; } }

使用literal来常见对象似乎很不错,比较直观,两个卷括号括起来就是个对象嘛,多清晰明了。但是如果你要创建一系列结构类似的对象,难道要这样一个个写吗?作为程序员我们的遵循的理念就是尽可能减少重复,也就是著名的DRY(Don"t Repeat Youself)。所以我们是无法容忍这么愚蠢的事情发生的,因此就有了构造函数,跟类有点相似,但我们这里不讨论类。构造函数就是建立一个模板,不绑定数据,只提供架构,你只需把相关数据填充到模板里就可以生成一个新的对象了:

3.构造函数
function NewObj(name,color){
    this.name = name;
    this.color = color;
    this.changeColor = function(c){
        this.color = c;
    }
}
var newObj1 = new NewObj("keti","red");

上面代码中,new是一个构造器,NewObj是我们创建好的模板,填入数据,赋给变量newObj1,ok,新的对象就这样生成了。

到此创建对象的方法似乎已经很不错了,但仔细观察我们还发现了新的问题:对于changeColor()这个方法事实上对所有instance来说是相同的,也就是说可以共享,不像name和color那样需要绑定给每个instance。而构造函数这种形式每次都会把自身的属性全部copy一份给每个instance,这就造成了不必要的浪费;并且,当我们想修改这个方法时,就必须重新生成所有的instance才能获得更新,比如说:


function NewObj(name,num){ this.name = name; this.num = num; this.changNum = function(c){ this.num = c; } } var newObj1 = new NewObj("kemi",10); newObj1.changNum(100); newObj1.num; //很明显是100

我现在想修改changNum()这个函数:


function NewObj(name,num){ this.name = name; this.num = num; this.changNum = function(c){ this.num = c*2; } } newObj1.changNum(100); newObj1.num; //依然是100,也就是说这个对象并不受我们修改的模板影响到

怎么解决这个问题呢?有一个原型对象。原型对象里的属性和方法并不是像构造函数自身属性一样copy给每个instance,而是“引用”,也可以理解为给每个instance提供一个指向该原型对象的指针,这样每个instance就能找到原型对象里的属性,而很明显,这是一种共享,也就是说,当你修改了这个原型里的属性,那么所有共享该属性的instance都能获得这个修改。因此,原型恰好解决了上面提到的两个问题。


function NewObj(name,num){ this.name = name; this.num = num; } NewObj.prototype.changNum = function(c){ this.num = c; } var newObj1 = new NewObj("kemi",10); newObj1.changNum(100); newObj1.num; //很明显是100 NewObj.prototype.changNum = function(c){ this.num = c*2; }//我们重新修改一下这个方法 newObj1.changNum(100); newObj1.num; //变成200了。

为什么一般情况下会把属性直接写在构造函数内,而方法通过prototype添加呢?这两种方式的区别上面其实已经有所展现了:大部分的instance的属性都是不同的,比如说name,因此在构造函数内通过this直接绑定给instance无疑是个好方案,而方法通常是通用的,使用prototype可以让每个instance共享同一个方法,而不用每个都copy一次,又能实现实时更新。

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

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

相关文章

  • 再谈JavaScript面向对象思想及继承

    摘要:面向对象中有三大特征,封装,继承,多态。这不仅无法做到数据共享,也是极大的资源浪费,那么引入对象实例对象的属性指向其构造函数,这样看起来实例对象好像继承了对象一样。实例对象的原型指向其构造函数的对象构造器的指向。 前言 为什么说是再谈呢,网上讲解这个的博客的很多,我开始学习也是看过,敲过就没了,自以为理解了就结束了,书到用时方恨少啊。实际开发中一用就打磕巴,于是在重新学习了之后分享出来...

    svtter 评论0 收藏0
  • js继承从入门到理解

    摘要:问题修改实例的,即修改了构造函数的原型对象的共享属性到此处,涉及到的内容大家可以再回头捋一遍,理解了就会觉得醍醐灌顶。 开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什么,prototype是什么,以及各种继承方法的优点和缺点,想必有好...

    不知名网友 评论0 收藏0
  • Javascript之bind

    摘要:返回的函数可以作为构造函数使用被用作构造函数时,应指向出来的实例,同时有属性,其指向实例的原型。判断当前被调用时,是用于普通的还是用于构造函数从而更改指向。运算符用来测试一个对象在其原型链中是否存在一个构造函数的属性。 写在最前 最近开始重新学习一波js,框架用久了有些时候觉得这样子应该可以实现发现就真的实现了,但是为什么这么写好像又说不太清楚,之前读了LucasHC以及冴羽的两篇关于...

    王岩威 评论0 收藏0
  • 我来重新学习 javascript 的面向对象(part 2)

    摘要:先来说其实构造函数也有,原型对象有,实例有也有,或者更加笼统的说,所有对象都是有的。构造函数的原型对象上的会指向构造函数。由于属性是可以变更的,所以未必真的指向对象的构造函数,只是一个提示。 续上一集内容,通过构造函数的方式,成功地更新了生产技术,老板笑呵呵,工人少奔波,只是问题总比办法多,又遇到一个新问题,就是会造成一些资源的重复和浪费,那么经过工程师们的智慧交流,他们产生了一个新技...

    silvertheo 评论0 收藏0
  • 初探js中的对象原型(Prototype

    摘要:在中,万物皆对象。在日常中,我们除了经常听到原型这个词之外,还经常会听到原型链这个词,那么这两个词到底有什么关系呢,下面我们就来探究一下。指向的对象往往被称为函数的原型。很简单,委托实际上就是原型链。 在JavaScript中,万物皆对象。每个对象都有一个特殊的内部属性,[[Prototype]](原型)。它是对于其他对象的引用,也就是说它关联到别的对象(如果它不为空)。 在日常中,我...

    fizz 评论0 收藏0
  • 【翻译】javascript中的prototype

    摘要:构造函数就是一个具有属性的方法,该属性被称作标识具有一个属性,但是没有用户定义它。然而,构造函数的属性可以被改变,并且将影响用这个原型创建的对象。 原文地址:http://dailyjs.com/2012/05/20/js101-prototype/ 在花费了很多年研究面向对象编程之后,想在javascript使用是令人失望的。主要是从根源上缺少一个class这样的关键词。然而,jav...

    lentrue 评论0 收藏0

发表评论

0条评论

0xE7A38A

|高级讲师

TA的文章

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