$.extend 的一个小问题


Posted in Javascript onJune 18, 2015

最近一直在搞移动端,也由于自己对jQuery比较熟悉,再加上Zepto提供了跟jQuery一样的API,所以就选择了Zepto作为开发框架。

由于是移动端开发,所以也应用了一些ES5新增的API,比如forEach,下面就是我写的代码的一些示例:

list.forEach(function(v) {
 return !!v;
})

我天真的以为forEach就跟jQuery的each一样,只要我的返回值为false,它就会中断循环,于是,类似这样的遍历代码写了不少(真的是懒得为每个遍历去声明变量啊)

写了一段时间之后我突然发现,forEach的回调函数并不能中断循环,于是,我便在Array.prototype上面挂了个函数,然后replaceAll,完美。

Array.prototype.foreach = function(fn) {
  var i = 0, len = this.length;

  for (; i < len; ++i) {

    if (fn(this[i], i) === false) {
     break;
    }
   }
 };

直到有一天,我想做点优化,考虑到客户端需要保存的json过大(没骗你,最大可以去到20M),stringify的时候太过耗时,会阻塞UI,所以我就用Worker在后台开个线程,专门用来stringify这个json,类似于这样子:

addEventListener("message", function(e) {

  var data = e.data;

  data = JSON.stringify(data);

  postMessage(data);

}, false);

posMesage:

worker.postMessage(data)

但是控制台却输出了以下的错误信息:

Uncaught DataCloneError: Failed to execute 'postMessage' on 'Worker': An object could not be cloned.

坑爹,这天杀的为什么连个json都复制不了,于是乎,我开始寻找原因,让我发现了我的json里面有这个东西:

天啊,这是什么鬼,这个foreach为什么跑进来了,我看了一下编辑器里面的$.extend(true, {}, obj)正在那里瑟瑟发抖,我不禁怀疑,不会是你丫的在作怪吧。于是乎,我查看了一下$.extend的源码:

function extend(target, source, deep) {
  for (key in source)
   if (deep && (isPlainObject(source[key]) || isArray(source[key]))) {
    if (isPlainObject(source[key]) && !isPlainObject(target[key]))
     target[key] = {}
    if (isArray(source[key]) && !isArray(target[key]))
     target[key] = []
    extend(target[key], source[key], deep)
   }
   else if (source[key] !== undefined) target[key] = source[key]
 }

 // Copy all but undefined properties from one or more
 // objects to the `target` object.
 $.extend = function(target){
  var deep, args = slice.call(arguments, 1)
  if (typeof target == 'boolean') {
   deep = target
   target = args.shift()
  }
  args.forEach(function(arg){ extend(target, arg, deep) })
  return target
 }

我的天啊,还真是这货在作怪啊,遍历数组用for...in..也就算了,但是 else if (source[key] !== undefined) target[key] = source[key] 这里的条件能不能严肃点啊,加个hasOwnProperty检查一下不会浪费多少时间吧。泪流满面

被Zepto坑了之后,我立马去找jQuery投诉,希望它能安慰我一下,没想到:

jQuery.extend = jQuery.fn.extend = function() {
  var options, name, src, copy, copyIsArray, clone,
    target = arguments[0] || {},
    i = 1,
    length = arguments.length,
    deep = false;

  // Handle a deep copy situation
  if ( typeof target === "boolean" ) {
    deep = target;
    target = arguments[1] || {};
    // skip the boolean and the target
    i = 2;
  }

  // Handle case when target is a string or something (possible in deep copy)
  if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
    target = {};
  }

  // extend jQuery itself if only one argument is passed
  if ( length === i ) {
    target = this;
    --i;
  }

  for ( ; i < length; i++ ) {
    // Only deal with non-null/undefined values
    if ( (options = arguments[ i ]) != null ) {
      // Extend the base object
      for ( name in options ) {
        src = target[ name ];
        copy = options[ name ];

        // Prevent never-ending loop
        if ( target === copy ) {
          continue;
        }

        // Recurse if we're merging plain objects or arrays
        if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
          if ( copyIsArray ) {
            copyIsArray = false;
            clone = src && jQuery.isArray(src) ? src : [];

          } else {
            clone = src && jQuery.isPlainObject(src) ? src : {};
          }

          // Never move original objects, clone them
          target[ name ] = jQuery.extend( deep, clone, copy );

        // Don't bring in undefined values
        } else if ( copy !== undefined ) {
          target[ name ] = copy;
        }
      }
    }
  }

  // Return the modified object
  return target;
};

这货也是 else if ( copy !== undefined ) {target[ name ] = copy;} 就交代了,我的亲娘啊。

最后迫不得已,只得自己写了一个。

总结:当你要使用$.extend的时候,不要轻易在Array.prototype和Object.prototype挂上你自定义的属性和方法,不然,你以后可能要去找bug了。

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
jQuery帮助之CSS尺寸(五)outerHeight、outerWidth
Nov 14 Javascript
javascript实现的基于金山词霸网络翻译的代码
Jan 15 Javascript
jquery实现鼠标拖动图片效果示例代码
Jan 09 Javascript
js字符串完全替换函数分享
Dec 03 Javascript
JavaScript学习笔记之JS事件对象
Jan 22 Javascript
JavaScript中Function()函数的使用教程
Jun 04 Javascript
javascript实现控制div颜色
Jul 07 Javascript
微信小程序 教程之WXML
Oct 18 Javascript
解析Vue2.0双向绑定实现原理
Feb 23 Javascript
详解vue中async-await的使用误区
Dec 05 Javascript
基于Three.js实现360度全景图片
Dec 30 Javascript
Javascript柯里化实现原理及作用解析
Oct 22 Javascript
纯js实现无限空间大小的本地存储
Jun 18 #Javascript
JS实现当前页居中分页效果的方法
Jun 18 #Javascript
javascript中Date()函数在各浏览器中的显示效果
Jun 18 #Javascript
javaScript中Math()函数注意事项
Jun 18 #Javascript
理解Javascript的动态语言特性
Jun 17 #Javascript
你所不了解的javascript操作DOM的细节知识点(一)
Jun 17 #Javascript
jQuery实现复选框批量选择与反选的方法
Jun 17 #Javascript
You might like
php之Smarty模板使用方法示例详解
2014/07/08 PHP
yii2实现 &quot;上一篇,下一篇&quot; 功能的代码实例
2017/02/04 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
js 加载并解析XML字符串的代码
2009/12/13 Javascript
js模拟select下拉菜单控件的代码
2013/05/08 Javascript
struts2+jquery组合验证注册用户是否存在
2014/04/30 Javascript
js与jquery回车提交的方法
2015/02/03 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
2015/09/15 Javascript
JS实现pasteHTML兼容ie,firefox,chrome的方法
2016/06/22 Javascript
Node.js中的child_process模块详解
2018/06/08 Javascript
js实现图片上传并预览功能
2018/08/06 Javascript
对Vue table 动态表格td可编辑的方法详解
2018/08/28 Javascript
javascript+HTML5 canvas绘制时钟功能示例
2019/05/15 Javascript
node.js实现http服务器与浏览器之间的内容缓存操作示例
2020/02/11 Javascript
vue插槽slot的简单理解与用法实例分析
2020/03/14 Javascript
vue+element实现图片上传及裁剪功能
2020/06/29 Javascript
[01:59]DOTA2首部纪录片《Free to play》预告片
2014/03/12 DOTA
[05:49]2014DOTA2TI4正赛第二日综述 昔日冠军纷纷落马 VG LGD占尽先机
2014/07/20 DOTA
[54:02]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 IG vs VGJ.T
2018/04/03 DOTA
Python实现字典排序、按照list中字典的某个key排序的方法示例
2018/12/18 Python
详解Python list和numpy array的存储和读取方法
2019/11/06 Python
python使用beautifulsoup4爬取酷狗音乐代码实例
2019/12/04 Python
tensorflow 保存模型和取出中间权重例子
2020/01/24 Python
python使用建议与技巧分享(一)
2020/08/17 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
html5 css3 动态气泡按钮实例演示
2012/12/02 HTML / CSS
Html5实现单张、多张图片上传功能
2019/04/28 HTML / CSS
介绍一下linux的文件权限
2012/02/15 面试题
计算机毕业生自荐信
2014/06/12 职场文书
药剂专业求职信
2014/06/20 职场文书
群众路线教育实践活动整改落实情况汇报
2014/10/28 职场文书
幼儿园中班教师个人总结
2015/02/05 职场文书
2015年企业团支部工作总结
2015/05/21 职场文书
HTML通过表单实现酒店筛选功能
2021/05/18 HTML / CSS
win11无法添加打印机怎么办? 提示windows无法打开添加打印机的解决办法
2022/04/05 数码科技