我们先来一个简单的构造函数+原型对象的小程序

         function CreateObj( uName, uAge ) {
this.userName = uName;
this.userAge = uAge;
}
CreateObj.prototype.showUserName = function () {
return this.userName;
}
CreateObj.prototype.showUserAge = function () {
return this.userAge;
}

这个程序,没有什么问题,但是非常的冗余,每次扩展一个方法,都要写一次原型对象,我们可以把原型对象prototype当做一个字面量对象,所有的方法都在字面

量对象中扩展,可以达到同样的效果:

         CreateObj.prototype = {
showUserAge : function(){
return this.userAge;
},
showUserName : function(){
return this.userName;
},
}
var obj1 = new CreateObj( 'ghostwu', 22 );
var obj2 = new CreateObj( '卫庄', 24 );
console.log( obj1.showUserName(), obj1.showUserAge() ); //ghostwu 22
console.log( obj2.showUserName(), obj2.showUserAge() ); //卫庄 24

但是这种原型(prototype)对象的写法,属于重写了CreateObj的默认原型对象,造成的第一个问题就是constructor不再指向CreateObj.

没有重写之前,constructor指向CreateObj

         function CreateObj( uName, uAge ) {
this.userName = uName;
this.userAge = uAge;
}
CreateObj.prototype.showUserName = function () {
return this.userName;
}
CreateObj.prototype.showUserAge = function () {
return this.userAge;
}
console.log( CreateObj.prototype.constructor === CreateObj ); //true

重写之后,constructor指向Object

         CreateObj.prototype = {
showUserAge : function(){
return this.userAge;
},
showUserName : function(){
return this.userName;
},
}
console.log( CreateObj.prototype.constructor === CreateObj ); //false
console.log( CreateObj.prototype.constructor === Object ); //true

所以说,constructor不能准确的标识对象,因为他会被修改

我们之前写的程序,基本都是在原型对象(prototype)上扩展完了方法之后,再实例化对象,我们看下,先实例化对象,再在原型对象(prototype)上扩展函数,

实例对象是否能正常的调用到扩展的方法?

         function CreateObj( uName, uAge ) {
this.userName = uName;
this.userAge = uAge;
}
var obj1 = new CreateObj( 'ghostwu', 22 );
CreateObj.prototype.showUserName = function(){
return this.userName;
}
console.log( obj1.showUserName() ); //ghostwu

可以正常调用,但是,如果原型对象是重写的,就调用不到了

         function CreateObj( uName, uAge ) {
this.userName = uName;
this.userAge = uAge;
}
var obj1 = new CreateObj( 'ghostwu', 22 );
CreateObj.prototype = {
showUserName : function(){
return this.userName;
}
}
console.log( obj1.showUserName() ); //报错

因为重写了原型对象之后,同时实例化又是在重写之前发生的,所以实例的隐式原型__proto__不会指向重写的原型对象,所以就调用不到

另一个问题,如果在原型对象(prototype)上有引用类型,千万小心,因为多个实例共用原型对象,只要有一个实例改变了引用类型的值,其他实例全部会收到

改变之后的结果

         function CreateObj(){}
CreateObj.prototype = {
name : 'ghostwu',
skills : [ 'php', 'javascript', 'linux' ]
};
var obj1 = new CreateObj();
obj1.skills.push( 'python' );
var obj2 = new CreateObj();
console.log( obj2.skills ); //'php', 'javascript', 'linux', 'python'

原型对象(prototype)的共享特性,可以很方便的为一些内置的对象扩展一些方法,比如,数组去重复

         Array.prototype.unique = function(){
var res = [];
for( var i = 0, len = this.length; i < len; i++ ){
if( res.indexOf( this[i] ) == -1 ) {
res.push( this[i] );
}
}
return res;
}
var arr = [ 10, 20, 30, 20, 30, 20, 40, 20 ];
console.log( arr.unique() ); //10, 20, 30, 40

但是,不要随便往内置的对象上面扩展方法,在多人协作开发,很容易产生覆盖,以及污染.

[js高手之路]使用原型对象(prototype)需要注意的地方的更多相关文章

  1. [js高手之路]从原型链开始图解继承到组合继承的产生

    基于javascript原型链的层层递进查找规则,以及原型对象(prototype)的共享特性,实现继承是非常简单的事情 一.把父类的实例对象赋给子类的原型对象(prototype),可以实现继承 f ...

  2. [js高手之路]原型对象(prototype)与原型链相关属性与方法详解

    一,instanceof: instanceof检测左侧的__proto__原型链上,是否存在右侧的prototype原型. 我在之前的两篇文章 [js高手之路]构造函数的基本特性与优缺点 [js高手 ...

  3. [js高手之路]一步步图解javascript的原型(prototype)对象,原型链

    我们接着上文继续,我们通过原型方式,解决了多个实例的方法共享问题,接下来,我们就来搞清楚原型(prototype),原型链的来龙去脉. function CreateObj(uName) { this ...

  4. [js高手之路] es6系列教程 - 对象功能扩展详解

    第一:字面量对象的方法,支持缩写形式 //es6之前,这么写 var User = { name : 'ghostwu', showName : function(){ return this.nam ...

  5. js高级——构造函数,实例对象和原型对象——prototype、__proto__和constructor构造器

    一.前言 了解JavaScript面向对象,需要先了解三个名词: 构造函数,实例对象和原型对象. 注意:JavaScript中没有类(class)的概念,取而代之的是构造函数,两者类似却又有很大的差别 ...

  6. [js高手之路]设计模式系列课程-组合模式+寄生组合继承实战新闻列表

    所谓组合模式,就是把一堆结构分解出来,组成在一起,现实中很多这样的例子,如: 1.肯德基套餐就是一种组合模式, 比如鸡腿堡套餐,一般是是由一个鸡腿堡,一包薯条,一杯可乐等组成的 2.组装的台式机同理, ...

  7. [js高手之路] 设计模式系列课程 - jQuery的extend插件机制

    这里在之前的文章[js高手之路] 设计模式系列课程 - jQuery的链式调用与灵活的构造函数基础上增加一个extend浅拷贝,可以为对象方便的扩展属性和方法, jquery的插件扩展机制,大致就是这 ...

  8. [js高手之路] es6系列教程 - 迭代器,生成器,for...of,entries,values,keys等详解

    接着上文[js高手之路] es6系列教程 - 迭代器与生成器详解继续. 在es6中引入了一个新的循环结构for ....of, 主要是用来循环可迭代的对象,那么什么是可迭代的对象呢? 可迭代的对象一般 ...

  9. [js高手之路] es6系列教程 - promise常见用法详解(resolve,reject,catch,then,all,race)

    关于promise我在之前的文章已经应用过好几次,如[js高手之路]Node.js+jade+express+mongodb+mongoose+promise实现todolist,本文就来讲解下pro ...

随机推荐

  1. ps_cc切片

    web前端开发的工作流程的第一步就是根据ui给的psd来还原设计图样貌. 可是一打开满屏的参考线.这时我们可以alt+v+d清空参考线 这时可以按alt+鼠标拖放图片.同时也可以按F进入半屏和匀速连按 ...

  2. ChartCtrl源码剖析之——CChartObject类

    首先,做一些简单的铺垫,目前针对ChartCtrl源码的剖析只针对V.15版本.名义上说是剖析,倒不如说是记录下自己针对该控件的理解,非常感谢Cedric Moonen大神,一切的功劳与掌声都该赠予给 ...

  3. JS - 数据类型的值拷贝函数(深拷贝)

    function mottoClone (obj) { if (obj === null || typeof obj !== 'object') return obj; if (obj instanc ...

  4. Pivot Table系列之切片器 (Slicer)

    1. 遇到的问题: 在Excel中,用PivotTable来做数据报告展示: 问题1:在同一个Sheet页里,多个PivotTable如何实现同步刷新? 问题2:在不同Sheet页之间,多个Pivot ...

  5. Hybris安装和各个Extention简单介绍

    前言:突然想好好梳理一下这几个月所学的内容了,顺便让自己的知识有一个系统的框架. 一.  安装JDK 请安装最新的Oracle JDK 8.0版(从Oracle官网下载). 二.开发工具建议使用 In ...

  6. linux kill杀死进程

    背景:这个命令总是记不住,在此稍作记录,方便查看! 1 杀死进程 1.1 查看进程 此时如果我想杀了火狐的进程就在终端输入: $ kill -s 9 1827 其中-s 9 制定了传递给进程的信号是9 ...

  7. API和schema开发过程问题汇总

    场景:在日常工作中很多都是重复性的劳动,有的坑踩过一次下次很可能还回踩到,所以很有必要将这些问题记录下来,提升工作效率! 1 API 2 schema 问题:提示schame中有元素没有定义 这个时候 ...

  8. div+css命名规范大全

    网页制作中规范使用DIV+CSS命名规则,可以改善优化功效特别是团队合作时候可以提供合作制作效率, 我们开发DIV+CSS网页(Xhtml)时候,比较困惑和纠结的事就是CSS命名,特别是新手不知道什么 ...

  9. GateSvr的设计2

    我们的目标是:1.业务Server集群部署,从网关发来的请求处理,程序自动找一台空闲的业务Server来处理这个请求,并将结果异步分发到服务网关,从而Push给客户端:2.一套业务Server挂了不会 ...

  10. 《深入理解Java虚拟机》虚拟机类加载机制

    上节学习回顾 上一节,我们深入到类文件去了解其结构细节,也大概对类文件的编写规则略知一二了,解析来我们就得学习这个类文件是如何被加载到Java虚拟机的,看看有什么引人入胜的奥秘. 本节学习重点 大部分 ...