在对象的原型上添加方法?

HTML5学堂:利利前段时间写了几个数组、字符串的方法,其中有一个是克隆(复制)一个数组。于是,最近一直在琢磨如何让这个复制变得更简单,可不可以把这个自定义的方法挂载在原型上呢?研究了几天,也算是得出一些基本的结论。本文除了讨论“在对象的原型上添加方法”好还是坏之外,也会为大家分享一个干货,是利利自己写的“复制”变量的方法。一起来看吧~!

本文主要内容

1 “复制”/“克隆”数组的功能需求

2 在对象的原型上添加方法是否合理?

3 “复制”各类变量的功能封装

“复制”/“克隆”数组的功能需求

最初的代码

刚开始的时候拿到这个需求,第一反应是用for循环,于是乎自己写出了如下的代码:

var arr = ["HTML5学堂", "利利", "堡堡"];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
    newArr[i] = arr[i];
};

额外提醒:可能有前端小伙伴考虑说直接var newArr = oldArr;岂不是更好,此处各位需要注意数组属于引用类型变量,这种书写方式是将oldArr的地址赋值给了newArr。oldArr和newArr指向同一个数组。

关于“引用类型变量与值类型变量”,如果不是太清楚的童鞋可以查看——>《引用类型变量的那个坑》

优化克隆功能

左看右看,总觉得for循环太复杂了,回顾数组的各类方法,突然想到了concat方法。concat方法的功能是基于当前数组中的所有项创建一个新数组,返回新数组。该方法会先创建一个当前数组的副本,然后将接收到的参数,添加到这个副本末尾,最后返回新构建的数组。当我们没有给concat方法传递参数时:复制当前数组并返回副本。

于是乎,功能代码就变成了这个样纸~~~

var arr = ["HTML5学堂", "利利", "堡堡"];
function clone(val) {
    return val.concat();
}
var newArr = clone(arr)

问题来了

实现了,但是要面临的问题来了,既然该方法能够实现,那么如果为了方便,我是不是可以为所有的数组元素都增加这个方法,将这个方法挂载到Array的原型上,即:

var arr = ["HTML5学堂", "利利", "堡堡"];
Array.prototype.clone = function() {
    return this.concat();
}
var newArr = arr.clone();

这样挂载到原型上,的确方便了我们的调用和开发,但是真的好么?

在对象的原型上添加方法是否合理?

仔细思考之后,并查阅了一些相关资料,利利最终还是放弃了将方法添加到对象的原型上,为什么呢?

1 防止冲突

我们可以想象,如果仅仅由我们一个人开发项目时,是不会出现什么冲突问题的,但是,如果参与项目的人不止一个,那么我在对象上定义一个方法,别人是不是也可以在对象上定义一个方法呢?此时,很容易出现冲突,并且,一旦造成冲突,之后就需要为了解决这个冲突而花费更多的时间,得不偿失。

2 不易定位错误位置

我们自己书写的代码,有时可能会有一些考虑不周,必然会产生或多或少的bug,如果这些方法是正常存在于window的全局作用域下,也可以通过JS文件寻找到相应内容时,那么,我们就可以比较快速的进行错误定位(采用注释法、断点调试、console命令等)。但是,当方法挂载在了原型上时,我们可能就很难发现问题的所在。简言之就是:出现Bug时,不容易进行问题的定位。

3 防止代码向上不兼容

关于这一条,查阅了比较多的信息,特别是getElementsByClassName~

所谓代码向上不兼容,指的是:我们定义了一个Array.prototype.clone,在当前的ECMAScript5.0(6.0)当中并没有这个方法,但是很有可能在ECMAScript7.0甚至更高版本当中出现这个方法,一旦出现这个方法,那么我们原有的代码就需要进行相关的修改。

额外扩展知识:当时实现document.getElementsByClassName,直接使用了document.prototype并返回了一个数组的实例(prototype返回的是Array)。但是DOM 后来原生方法里对这个方法返回的是一个Nodelist实例,结果就是之前用了Prototype库的代码,运行在新浏览器的时候,用的是DOM原生方法,返回的对象是无法继承数组的任何方法的,所以就会报错。

“复制”各类变量的功能封装

虽然放弃了将变量“复制”的功能放在原型上,但是依旧打算对这个功能进行一些扩展,封装一个能够克隆数字、字符串、数组、对象等多种数据的功能函数,岂不是更好?于是乎~~~

var arr = ["HTML5学堂", "利利", "堡堡"];
function clone(targetObj) {
    if (targetObj instanceof Array) {
        return targetObj.concat();
    } else if (targetObj instanceof Object) {
        var newObj = {};
        for (var i in targetObj) {
            newObj[i] = targetObj[i];
        };
        return newObj;
    } else {
        return targetObj;
    }
}
var result = clone(arr);
console.log(result);

HTML5小编-利利 耗时3h

原文发布于微信公众号 - HTML5学堂(h5course-com)

原文发表时间:2016-03-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

腾讯2013年实习生笔试题目(附答案)

下面是我在参加2013年腾讯实习生招聘的笔试题目,当然啦,我个人不可能是完全的记住所有题目,部分是摘自网络的。同时,下面也有一些题目我不会的,希望大家一起商量解...

42280
来自专栏林德熙的博客

C# 使用外部别名

在看过 C# 很少人知道的科技的小伙伴就知道,我告诉了大家一些关键字,都是很少人发现。

9510
来自专栏公众号_薛勤的博客

Java多线程核心技术(六)线程组与线程异常

调用与线程有关的方法是造成线程状态改变的主要原因,其关系如图所示:(图片来源于网络)

10720
来自专栏喔家ArchiSelf

全栈必备 Java基础

那一年,从北邮毕业,同一年,在大洋的彼岸诞生了一门对软件业将产生重大影响的编程语言,它就是——Java。1998年的时候,开始学习Java1.2,并在Java ...

14140
来自专栏来自地球男人的部落格

Python切片赋值操作

1. 问题 首先来看一小段列表推到的python代码 a = [1,2,3] b = a # 赋值1 b[:] = [x+1 for x in a] print...

25570
来自专栏老付的网络博客

程序如何运行的

在写代码的时候,我们直接在没有编译报错的时候,直接点击运行后,ide会直接把程序的结果输出到控制台上,代码如下:

21050
来自专栏Java学习网

Java 实现线程死锁

Java 实现线程死锁 概述 春节的时候去面试了一家公司,笔试题里面有一道是使用简单的代码实现线程的‘死锁’,当时没有想到这道题考的是Synchronized关...

26960
来自专栏一个会写诗的程序员的博客

《Java核心技术》 Class类文件结构开篇Class类文件结构

这就是jvm的byte code字节码。这一串“天书”,如果不看JVM虚拟机规范的人,正常的智商,是看不懂的。

11230
来自专栏玄魂工作室

如何学python-第六课 流程控制-IF,ELSE,条件语句

在上一篇文章里,我们介绍了流程控制的概念,并介绍了布尔类型。今天,我们会把上节课学到的东西与 if、else结合起来使用。 条件判断语句 条件判断语句会根据语句...

36180
来自专栏V站

如何提高PHP编程效率,提升程序编译质量(53条)

用单引号代替双引号来包含字符串,这样做会更快一些。因为PHP会在双引号包围的字符串中搜寻变量,单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串...

17250

扫码关注云+社区

领取腾讯云代金券