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

         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. POJ 2251 三维BFS(基础题)

    Dungeon Master Description You are trapped in a 3D dungeon and need to find the quickest way out! Th ...

  2. vue vuex 提交 this.$store.commit({type: 'setSelectPro', selectPro: this.productId});

    1.store.commit({'type':'mutation','parameter':'value'}); store.dispatch('action'); 2.获取state保存的值 sto ...

  3. CSS预编译与PostCSS以及Webpack构建CSS综合方案

    CSS全称Cascading Style Sheets(层叠样式表),用来为HTML添加样式,本质上是一种标记类语言.CSS前期发展非常迅速,1994年哈肯·维姆·莱首次提出CSS,1996年12月W ...

  4. JQuery学习笔记——层级选择器

    JQuery学习笔记--层级选择器 上一篇学习了基础的五种选择,分别是id选择器,class选择器,element选择器,*选择器 和 并列选择器.根据手册大纲,这篇学习的是层级选择器. 选择器: 1 ...

  5. SpringMVC源码情操陶冶-ViewResolver视图解析

    简单分析springmvc是如何解析view视图,并返回页面给前端 SpringMVC配置视图解析器 <bean id="viewResolver" class=" ...

  6. Angular4.0学习笔记 从入门到实战打造在线竞拍网站学习笔记之二--路由

    Angular4.0基础知识见上一篇博客 路由 简介 接下来学习路由的相关知识 本来是不准备写下去的,因为当时看视频学的时候感觉自己掌握的不错 ( 这是一个灰常不好的想法 ) ,过了一段时间才发现An ...

  7. Java curator操作zookeeper获取kafka

    Java curator操作zookeeper获取kafka Curator是Netflix公司开源的一个Zookeeper客户端,与Zookeeper提供的原生客户端相比,Curator的抽象层次更 ...

  8. hdu--1072--Nightmare(bfs回溯)

    Nightmare Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total S ...

  9. Vmware虚拟机安装win7系统教程

    第一步:下载虚拟机 可以下载VMware虚拟机,这里用的是Vmware12专业版,百度网盘直通车密码:c3mt密钥:5A02H-AU243-TZJ49-GTC7K-3C61N 第二部:安装 第三部:做 ...

  10. js数组遍历和对象遍历

    针对js各种遍历作一个总结分析,从类型用处:分数组遍历和对象遍历:还有性能,优缺点等. JS数组遍历: 1,普通for循环,经常用的数组遍历 var arr = [1,2,0,3,9]; for ( ...