最近在写移动端的项目,目前尚未引用任何库,因此不少的方法都要本身写。jquery
用惯了jQuery,当函数参数是对象的时候,定义默认参数的时候会写一个defaultOptions对象,而后经过jQuery.extend
将实参扩展到defaultOptions对象上。JavaScript是没有extend
这个原生方法的,今日得闲,就本身实现一个吧。api
先想一想这个函数须要作什么。jQuery extend文档中描述的jQuery.extend
原型是
jQuery.extend( target [, object1 ] [, objectN ] )函数
它的含义是将object一、object2...合并到target中,并返回合并过的target。这里面有两个点须要注意一下。优化
其实若不想原始数据被更改也很简单,只要第一个参数传空对象就行了。prototype
那,直接上代吗吧:code
void function(global){ var extend, _extend, _isObject; _isObject = function(o){ return Object.prototype.toString.call(o) === '[object Object]'; } _extend = function self(destination, source){ for (var property in source) { if (source.hasOwnProperty(property)) { // 若sourc[property]是对象,则递归 if (_isObject(source[property])) { // 若destination没有property,赋值空对象 if (!destination.hasOwnProperty(property)) { destination[property] = {}; }; // 对destination[property]不是对象,赋值空对象 if (!_isObject(destination[property])) { destination[property] = {}; }; // 递归 self(destination[property], source[property]); } else { destination[property] = source[property]; }; } } } extend = function(){ var arr = arguments, result = {}, i; if (!arr.length) return {}; for (i = 0; i < arr.length; i++) { if (_isObject(arr[i])) { _extend(result, arr[i]) }; } arr[0] = result; return result; } global.extend = extend; }(window)
这样彷佛能够了。可是貌似有一个小问题,咱们这里是按照参数顺序从左到右依次执行的,可是其实如果最后一个参数有的属性,前面的参数上的该属性都不须要再扩展了。其实前面的全部参数都是将本身身上有的属性而最后一个参数没有的属性补到最后一个参数上。既如此,是否是从参数列表的右侧开始扩展更好一些。对象
修改之后的代码:递归
void function(global){ var extend, _extend, _isObject; _isObject = function(o){ return Object.prototype.toString.call(o) === '[object Object]'; } _extend = function self(destination, source) { var property; for (property in destination) { if (destination.hasOwnProperty(property)) { // 若destination[property]和sourc[property]都是对象,则递归 if (_isObject(destination[property]) && _isObject(source[property])) { self(destination[property], source[property]); }; // 若sourc[property]已存在,则跳过 if (source.hasOwnProperty(property)) { continue; } else { source[property] = destination[property]; } } } } extend = function(){ var arr = arguments, result = {}, i; if (!arr.length) return {}; for (i = arr.length - 1; i >= 0; i--) { if (_isObject(arr[i])) { _extend(arr[i], result); }; } arr[0] = result; return result; } global.extend = extend; }(window)
写代码老是那么有意思!这里面能够看到,只要result身上有的属性,都不须要再赋值了,嘿嘿。ip
固然,目前水平有限,这段代码确定也还有着优化空间,若看官有任何建议,还请不吝赐教。文档