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 相关文章推荐
JavaScript高级程序设计 阅读笔记(二十一) JavaScript中的XML
Sep 14 Javascript
JavaScript的9种继承实现方式归纳
May 18 Javascript
VueJS 集成 Medium Editor的示例代码 (自定义编辑器按钮)
Aug 24 Javascript
vuex学习之Actions的用法详解
Aug 29 Javascript
谈谈vue中mixin的一点理解
Dec 12 Javascript
Vue底层实现原理总结
Feb 17 Javascript
使用javascript做在线算法编程
May 25 Javascript
django中使用vue.js的要点总结
Jul 07 Javascript
JS中==、===你分清楚了吗
Mar 04 Javascript
JavaScript设计模式--桥梁模式引入操作实例分析
May 23 Javascript
详解JavaScript之Array.reduce源码解读
Nov 01 Javascript
vue中实现点击空白区域关闭弹窗的两种方法
Dec 30 Vue.js
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 输出URL的快捷方式示例代码
2013/09/22 PHP
PHP扩展开发教程(总结)
2015/11/04 PHP
PHP的AES加密算法完整实例
2016/07/20 PHP
thinkphp3.2实现在线留言提交验证码功能
2017/07/19 PHP
关于Javascript模块化和命名空间管理的问题说明
2010/12/06 Javascript
javascript下拉框选项单击事件的例子分享
2015/03/04 Javascript
JS正则表达式比较常见用法
2016/01/26 Javascript
pc加载更多功能和移动端下拉刷新加载数据
2016/11/07 Javascript
jQuery插件zTree实现删除树节点的方法示例
2017/03/08 Javascript
AngularJS创建一个上传照片的指令实例代码
2018/02/24 Javascript
vue基于mint-ui实现城市选择三级联动
2020/06/30 Javascript
让webpack+vue-cil项目不再自动打开浏览器的方法
2018/09/27 Javascript
webpack 从指定入口文件中提取公共文件的方法
2018/11/13 Javascript
小白教程|一小时上手最流行的前端框架vue(推荐)
2019/04/10 Javascript
详解基于Vue的支持数据双向绑定的select组件
2019/09/02 Javascript
[03:16]DOTA2完美大师赛小组赛精彩集锦
2017/11/22 DOTA
python中pygame模块用法实例
2014/10/09 Python
为Python的web框架编写MVC配置来使其运行的教程
2015/04/30 Python
Python卸载模块的方法汇总
2016/06/07 Python
python3 读写文件换行符的方法
2018/04/09 Python
Scrapy基于selenium结合爬取淘宝的实例讲解
2018/06/13 Python
TensorFlow用expand_dim()来增加维度的方法
2018/07/26 Python
python 产生token及token验证的方法
2018/12/26 Python
python3中利用filter函数输出小于某个数的所有回文数实例
2019/11/24 Python
CSS+jQuery实现的在线答题功能
2015/04/25 HTML / CSS
船餐厅和泰晤士河餐饮游轮:Bateaux London
2018/03/19 全球购物
init进程的作用
2015/08/20 面试题
Ruby如何进行文件操作
2014/07/17 面试题
标准毕业生自荐信范文
2013/11/04 职场文书
竞聘书格式及范文
2014/03/31 职场文书
艺术设计专业个人求职信
2014/04/10 职场文书
酒店保洁员岗位职责
2015/02/26 职场文书
吃通javascript正则表达式
2021/04/21 Javascript
微信小程序实现录音Record功能
2021/05/09 Javascript
Redis基本数据类型List常用操作命令
2022/06/01 Redis
Python使用pandas导入csv文件内容的示例代码
2022/12/24 Python