$.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 相关文章推荐
JS判断两个时间大小的示例代码
Jan 28 Javascript
node.js中实现同步操作的3种实现方法
Dec 05 Javascript
JavaScript解析json格式数据简单示例
Dec 09 Javascript
jQuery给多个不同元素添加class样式的方法
Mar 26 Javascript
动态加载js文件简单示例
Apr 21 Javascript
vue开发心得和技巧分享
Oct 27 Javascript
jQuery实现立体式数字动态增加(animate方法)
Dec 21 Javascript
JavaScript事件方法(实例讲解)
Jun 27 Javascript
jQuery实现动态添加节点与遍历节点功能示例
Nov 09 jQuery
微信小程序动态添加view组件的实例代码
May 23 Javascript
初学vue出现空格警告的原因及其解决方案
Oct 31 Javascript
Vue中关闭弹窗组件时销毁并隐藏操作
Sep 01 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
php5编程中的异常处理详细方法介绍
2008/07/29 PHP
PHP中实现中文字符进制转换原理分析
2011/12/06 PHP
PHP输出图像imagegif、imagejpeg与imagepng函数用法分析
2016/11/14 PHP
微信小程序 消息推送php服务器验证实例详解
2017/03/30 PHP
js的闭包的一个示例说明
2008/11/18 Javascript
jQuery实现鼠标经过图片预览大图效果
2014/04/10 Javascript
javascript进行数组追加方法小结
2014/06/16 Javascript
JavaScript测试工具之Karma-Jasmine的安装和使用详解
2015/12/03 Javascript
js代码实现点击按钮出现60秒倒计时
2021/01/28 Javascript
JavaScript中Object.prototype.toString方法的原理
2016/02/24 Javascript
js对字符串进行编码的方法总结(推荐)
2016/11/10 Javascript
jquery+css3实现熊猫tv导航代码分享
2018/02/12 jQuery
element-ui table span-method(行合并)的实现代码
2018/12/20 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
2019/01/18 Javascript
微信小程序组件传值图示过程详解
2019/07/31 Javascript
手把手带你入门微信小程序新框架Kbone的使用
2020/02/25 Javascript
JS页面动态绘图工具SVG,Canvas,VML介简介
2020/10/16 Javascript
jupyter notebook引用from pyecharts.charts import Bar运行报错
2020/04/23 Python
对python实现合并两个排序链表的方法详解
2019/01/23 Python
Python数据类型之Tuple元组实例详解
2019/05/08 Python
Python 读取有公式cell的结果内容实例方法
2020/02/17 Python
QML用PathView实现轮播图
2020/06/03 Python
Python第三方库安装缓慢的解决方法
2021/02/06 Python
DELPHI中如何调用API,可举例说明
2014/01/16 面试题
精彩的推荐信范文
2013/11/26 职场文书
上课玩手机检讨书
2014/02/08 职场文书
棉花姑娘教学反思
2014/02/15 职场文书
《陶罐和铁罐》教学反思
2014/02/19 职场文书
教师师德承诺书
2014/03/26 职场文书
领导干部廉政自律承诺书
2014/05/26 职场文书
员工安全责任书范本
2014/07/24 职场文书
英语课外活动总结
2014/08/27 职场文书
工作表扬信范文
2015/01/17 职场文书
2015年信访工作总结
2015/04/07 职场文书
计划生育责任书
2015/05/09 职场文书
教你使用RustDesk 搭建一个自己的远程桌面中继服务器
2022/08/14 Servers