关于extend的一些思考

JS 拷贝是一个在我们开发中经常遇到的一个问题,我们通过使用extend这个函数来实现一些JS的复用。

比如下面的代码:

var _default = { address: "上海市静安区", sex: "男" };
var user = $.extend({}, _default,{name:"小亮", age:12});
console.log(user) //=> {name:"小亮", address: "上海市静安区",age:12}

这是一个开发中经常遇到的一个场景,我们通过复用一些默认的配置,减少了代码开发量。这里我是用的$.extend是jQuery提供的一个静态拷贝函数。它在这里的作用就是把_default 和 {name:"小亮",age:12}的属性合并到 {} 中,并且返回。

自己如何实现

作为一个程序员,我们不仅仅需要知其然,还是知其所以然,所以我们不仅是需要知道怎么使用,也需要明白其中的实现和原理,以及一些我们需要注意的事项。

第一步: 入口参数处理

extend = function (x, y, z, ......) { ...... }

extend这个函数的功能是把除第一个参数外,其它参数的属性合并到第一个参数,那我们是不知道总共有多少个参数,所以我们需要使用到 arguments 这个对象去获取参数,当然了,如果是在ES6的情况下,我们就不需要使用arguments这个参数对象了。

extend = function (x, y, z, ......) { console.log(arguments) //=> [x,y,z ......] console.log(arguments[0]) //=> x console.log(arguments[1]) //=> y ...... }

这里arguments 是一个类数组对象,可以通过arguments的下标获取相关的参数值,但是没有实现数组相关的方法。所以,我们有时候需要把arguments这个参数对象转化为数组。

var argus = Array.prototype.slice.call(arguments);

这样我们就能够获取extend函数的不定参数

第二步: 数据拷贝

在开始进行数据拷贝之前,我们应该需要确认两个问题。

  1. 我们获取到参数以后,第一个参数,应该是作为我们的base对象,后面的对象把他们的属性放到这个base对象上,而且是依次执行的。 这样的话,后面属性值会把前面的属性值给进行覆盖。

  2. 就是需要对参数类型进行判断, 按照日常的开发需求来说,我们这里是只需要纯 Object 对象,那么像Number,Boolean,String,Function, Array...... 这种如果出现在参数里面。那么从功能角度来说,这些数据是无用数据,所以这些数据会被过滤掉。

Object.prototype.toString.call(obj) === "[object Object]" //=> true

那么我们开始进入正题,实现extend的拷贝

var isObj = function (obj) { return Object.prototype.toString.call(obj) === "[object Object]"; };
var extend = function(base) { // argus 表示除 base 后面的列表集合 var argus = Array.prototype.slice.call(arguments,1),obj,key; base = isObj(base) ? base : {}; for (var index = 0, length = argus.length; index < length; index++) { obj = argus[index]; if (isObj(obj)) { // 防止非纯Object对象 for (key in obj) { if (obj.hasOwnProperty(key)) { base[key] = obj[key]; } } } } return base; }

测试用例

extend({},{a:1},{b:1}); //=> Object {a: 1, b: 1}
extend({a:1},{b:1}); //=> Object {a:1, b:1}
extend({},[1,2,3]); //=> Object {}
extend({},{aa : function() { alert("aa")}}); //=>Object{aa:()}
extend(null,{aa : 111 }); //=>Object{aa :111}

到此,我们已经完成了 extend 这个函数基本骨架。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 12,388评论 2 17
  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 6,469评论 1 10
  • 三、闭包和高阶函数 3.1 闭包 3.1.1 变量的作用域 所谓变量的作用域,就是变量的有效范围。通过作用域的划分...
    梁同学de自言自语阅读 5,339评论 0 6
  • @转自GitHub 介绍js的基本数据类型。Undefined、Null、Boolean、Number、Strin...
    YT_Zou阅读 4,952评论 0 0
  • 我总是给最爱自己的人伤害, 又总是在突然失去爱后懊悔不已,原来爱很简单 以爱之名,他最近看起来又添上了几缕银丝,好...
    木子口儿阅读 3,097评论 0 0

友情链接更多精彩内容