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 相关文章推荐
JQuery AJAX实现目录浏览与编辑的代码
Oct 21 Javascript
详谈 Jquery Ajax异步处理Json数据.
Sep 09 Javascript
基于mootools插件实现遮罩层新手引导
May 24 Javascript
js unicode 编码解析关于数据转换为中文的两种方法
Apr 21 Javascript
JS在IE下缺少标识符的错误
Jul 23 Javascript
JS实现很实用的对联广告代码(可自适应高度)
Sep 18 Javascript
浅谈node.js中async异步编程
Oct 22 Javascript
Jquery获取当前城市的天气信息
Aug 05 Javascript
Bootstrap框架的学习教程详解(二)
Oct 18 Javascript
Vue的elementUI实现自定义主题方法
Feb 23 Javascript
解决mpvue + vuex 开发微信小程序vuex辅助函数mapState、mapGetters不可用问题
Aug 03 Javascript
JavaScript隐式类型转换代码实例
May 29 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
追忆往昔!浅谈收音机的百年发展历史
2021/03/01 无线电
我常用的几个类
2006/10/09 PHP
PHP Memcached + APC + 文件缓存封装实现代码
2010/03/11 PHP
PHP5下$_SERVER变量不再受magic_quotes_gpc保护的弥补方法
2012/10/31 PHP
php中使用临时表查询数据的一个例子
2013/02/03 PHP
基于initPHP的框架介绍
2013/04/18 PHP
再推荐十款免费的php开发工具
2015/11/09 PHP
Yii2中设置与获取别名的函数(setAlias和getAlias)用法分析
2016/07/25 PHP
checkbox设置复选框的只读效果不让用户勾选
2013/08/12 Javascript
Eclipse下jQuery文件报错出现错误提示红叉
2014/01/13 Javascript
js实现点击左右按钮轮播图片效果实例
2015/01/29 Javascript
JS实现仿FLASH效果的竖排导航代码
2015/09/15 Javascript
详解JavaScript模块化开发
2016/12/04 Javascript
详解jQuery lazyload 懒加载
2016/12/19 Javascript
js推箱子小游戏步骤代码解析
2018/01/10 Javascript
vue单个组件实现无限层级多选菜单功能
2018/04/10 Javascript
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
使用grappelli为django admin后台添加模板
2014/11/18 Python
Python中操作文件之write()方法的使用教程
2015/05/25 Python
python统计文本字符串里单词出现频率的方法
2015/05/26 Python
详细介绍Python的鸭子类型
2016/09/12 Python
Python3使用PyQt5制作简单的画板/手写板实例
2017/10/19 Python
基于Python的文件类型和字符串详解
2017/12/21 Python
python实现换位加密算法的示例
2018/10/14 Python
python3.7 利用函数os pandas利用excel对文件名进行归类
2019/09/29 Python
python实现大量图片重命名
2020/03/23 Python
python面向对象之类属性和类方法案例分析
2019/12/30 Python
Python对Tornado请求与响应的数据处理
2020/02/12 Python
Python常用数据分析模块原理解析
2020/07/20 Python
C#里面如何判断一个Object是否是某种类型(如Boolean)?
2016/02/10 面试题
几个常见的软件测试问题
2016/09/07 面试题
标准毕业生自荐信范文
2013/11/04 职场文书
先进教师事迹材料
2014/12/16 职场文书
全陪导游词开场白
2015/05/29 职场文书
保险公司2016开门红口号集锦
2015/12/24 职场文书
Sleuth+logback 设置traceid 及自定义信息方式
2021/07/26 Java/Android