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 相关文章推荐
用JS判别浏览器种类以及IE版本的几种方法小结
Aug 02 Javascript
JQuery的read函数与js的onload不同方式实现
Mar 18 Javascript
js调用AJAX时Get和post的乱码解决方法
Jun 04 Javascript
设为首页和收藏的Javascript代码(亲测兼容IE,Firefox,chrome等浏览器)
Nov 18 Javascript
jQuery和AngularJS的区别浅析
Jan 29 Javascript
JS截取字符串实例详解
Nov 24 Javascript
JavaScript学习笔记之检测客户端类型是(引擎、浏览器、平台、操作系统、移动设备)
Dec 03 Javascript
javascript日期验证之输入日期大于等于当前日期
Dec 13 Javascript
JavaScript数据绑定实现一个简单的 MVVM 库
Apr 08 Javascript
遍历js中对象的属性和值的实例
Nov 21 Javascript
详解Vue中使用插槽(slot)、聚类插槽
Apr 12 Javascript
JS实现拼图游戏
Jan 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
1 Tube Radio
2021/03/02 无线电
PHP 中的一些经验积累
2006/10/09 PHP
基于PHP的cURL快速入门教程 (小偷采集程序)
2011/06/02 PHP
判断Keep-Alive模式的HTTP请求的结束的实现代码
2011/08/06 PHP
一漂亮的PHP图片验证码实例
2014/03/21 PHP
thinkPHP批量删除的实现方法分析
2016/11/09 PHP
PHP中include()与require()的区别说明
2017/02/14 PHP
PDO操作MySQL的基础教程(推荐)
2017/08/18 PHP
TP5框架请求响应参数实例分析
2019/10/17 PHP
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
鼠标移入移出事件改变图片的分辨率的两种方法
2013/12/17 Javascript
ECMAScript6块级作用域及新变量声明(let)
2015/06/12 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
Nodejs中 npm常用命令详解
2016/07/04 NodeJs
微信小程序实现的贪吃蛇游戏【附源码下载】
2018/01/03 Javascript
vue项目tween方法实现返回顶部的示例代码
2018/03/02 Javascript
JS对象和字符串之间互换操作实例分析
2019/02/02 Javascript
解决angular 使用原生拖拽页面卡顿及表单控件输入延迟问题
2020/04/21 Javascript
JavaScript数组类型Array相关的属性与方法详解
2020/09/08 Javascript
[02:38]DOTA2亚洲邀请赛 IG战队巡礼
2015/02/03 DOTA
[42:32]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第二场 10.28
2020/10/28 DOTA
python通过urllib2获取带有中文参数url内容的方法
2015/03/13 Python
python动态性强类型用法实例
2015/05/09 Python
Python字符串特性及常用字符串方法的简单笔记
2016/01/04 Python
Python对文件操作知识汇总
2016/05/15 Python
用pandas按列合并两个文件的实例
2018/04/12 Python
Django Admin后台添加数据库视图过程解析
2020/04/01 Python
python 如何调用远程接口
2020/09/11 Python
台湾流行服饰购物平台:OB严选
2018/01/21 全球购物
生产现场工艺工程师岗位职责
2013/11/28 职场文书
餐饮周年庆活动方案
2014/08/14 职场文书
2014公司党员自我评价范文
2014/09/11 职场文书
使用pycharm运行flask应用程序的详细教程
2021/06/07 Python
mybatis源码解读之executor包语句处理功能
2022/02/15 Java/Android
Android Studio 计算器开发
2022/05/20 Java/Android
javascript进阶篇深拷贝实现的四种方式
2022/07/07 Javascript