js使用原型对象(prototype)需要注意的地方


Posted in Javascript onAugust 28, 2017

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

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
Mar 11 Javascript
一个JS的日期格式化算法示例
Jul 31 Javascript
node.js实现端口转发
Apr 14 Javascript
第四篇Bootstrap网格系统偏移列和嵌套列
Jun 21 Javascript
你不知道的 javascript【推荐】
Jan 08 Javascript
基于React实现表单数据的添加和删除详解
Mar 14 Javascript
浅谈vue实现数据监听的函数 Object.defineProperty
Jun 08 Javascript
vue.js 添加 fastclick的支持方法
Aug 28 Javascript
extract-text-webpack-plugin用法详解
Feb 14 Javascript
基于vue实现滚动条滚动到指定位置对应位置数字进行tween特效
Apr 18 Javascript
微信小程序webview组件交互,内联h5页面并网页实现微信支付实现解析
Aug 16 Javascript
vue vantUI实现文件(图片、文档、视频、音频)上传(多文件)
Oct 15 Javascript
vue2.0移除或更改的一些东西(移除index key)
Aug 28 #Javascript
详解基于Angular4+ server render(服务端渲染)开发教程
Aug 28 #Javascript
JS实现图片手风琴效果
Apr 17 #Javascript
vue服务端渲染的实例代码
Aug 28 #Javascript
jQuery 1.9版本以上的浏览器判断方法代码分享
Aug 28 #jQuery
使用react-router4.0实现重定向和404功能的方法
Aug 28 #Javascript
vue.js路由跳转详解
Aug 28 #Javascript
You might like
PHP 5.0对象模型深度探索之属性和方法
2008/03/27 PHP
php结合表单实现一些简单功能的例子
2011/06/04 PHP
PHP中去掉字符串首尾空格的方法
2012/05/19 PHP
PHP编程中的__clone()方法使用详解
2015/11/27 PHP
php写app接口并返回json数据的实例(分享)
2017/05/20 PHP
用javascript获取地址栏参数
2006/12/22 Javascript
JQuery 插件制作实践 xMarquee插件V1.0
2010/04/02 Javascript
Angular的Bootstrap(引导)和Compiler(编译)机制
2016/06/20 Javascript
Javascript使用uploadify来实现多文件上传
2016/11/16 Javascript
微信公众号开发 实现点击返回按钮就返回到聊天界面
2016/12/15 Javascript
Node.js实现mysql连接池使用事务自动回收连接的方法示例
2018/02/03 Javascript
JavaScript中常用的简洁高级技巧总结
2019/03/10 Javascript
vue-froala-wysiwyg 富文本编辑器功能
2019/09/19 Javascript
three.js利用卷积法如何实现物体描边效果
2019/11/27 Javascript
微信小程序的引导页实现代码
2020/06/24 Javascript
javascript实现京东快递单号的查询效果
2020/11/30 Javascript
[02:27]2018DOTA2亚洲邀请赛赛前采访-OpTic
2018/04/03 DOTA
[49:17]DOTA2-DPC中国联赛 正赛 Phoenix vs Dynasty BO3 第三场 1月26日
2021/03/11 DOTA
python实现代码行数统计示例分享
2014/02/10 Python
Python 使用PIL numpy 实现拼接图片的示例
2018/05/08 Python
Python中反射和描述器总结
2018/09/23 Python
Python面向对象之类和对象属性的增删改查操作示例
2018/12/14 Python
Python统计一个字符串中每个字符出现了多少次的方法【字符串转换为列表再统计】
2019/05/05 Python
Python一行代码解决矩阵旋转的问题
2019/11/30 Python
Python爬虫防封ip的一些技巧
2020/08/06 Python
Python爬虫进阶之爬取某视频并下载的实现
2020/12/08 Python
matplotlib更改窗口图标的方法示例
2021/02/03 Python
Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
2015/01/27 面试题
企业申诉管理制度
2014/01/30 职场文书
2014年手术室工作总结
2014/11/26 职场文书
招标保密承诺书
2015/01/20 职场文书
2015年中学图书馆工作总结
2015/07/22 职场文书
中国文明网2015年“向国旗敬礼”活动网上签名寄语
2015/09/24 职场文书
小学数学教学反思范文
2016/02/16 职场文书
一篇带你入门Java垃圾回收器
2021/06/16 Java/Android
星际争霸:毕姥爷vs解冻01
2022/04/01 星际争霸