$.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 相关文章推荐
JavaScript CSS菜单功能 改进版
Dec 20 Javascript
Javascript在IE和FireFox中的不同表现简析
Dec 03 Javascript
javascript-表格排序(降序/反序)实现介绍(附图)
May 30 Javascript
实用框架(iframe)操作代码
Oct 23 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
Jan 13 Javascript
Bootstrap modal使用及点击外部不消失的解决方法
Dec 13 Javascript
深入理解JavaScript中的for循环
Feb 07 Javascript
javascript 删除数组元素和清空数组的简单方法
Feb 24 Javascript
webpack中使用iconfont字体图标的方法
Feb 22 Javascript
最适应的vue.js的form提交涉及多种插件【推荐】
Aug 27 Javascript
基于JS实现web端录音与播放功能
Apr 17 Javascript
vue 解决IOS10低版本白屏的问题
Nov 17 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语言认识上需要避免的10大误区
2014/06/12 PHP
基于PHP实现数据分页显示功能
2016/05/26 PHP
thinkphp框架类库扩展操作示例
2019/11/26 PHP
php图像生成函数之间的区别分析
2012/12/06 Javascript
深入理解jQuery中live与bind方法的区别
2013/12/18 Javascript
javascript实现的平方米、亩、公顷单位换算小程序
2014/08/11 Javascript
Javascript检查图片大小不要让大图片撑破页面
2014/11/04 Javascript
AngularJS基础学习笔记之简单介绍
2015/05/10 Javascript
基于jQuery通过jQuery.form.js插件使用ajax提交form表单
2015/08/17 Javascript
JavaScript生成带有缩进的表格代码
2016/06/15 Javascript
详解Angular.js指令中scope类型的几种特殊情况
2017/02/21 Javascript
JS触摸与手势事件详解
2017/05/09 Javascript
js实现可以点击收缩或张开的悬浮窗
2017/09/18 Javascript
深入浅出webpack之externals的使用
2017/12/04 Javascript
浅谈js闭包理解
2019/04/01 Javascript
浅析vue-cli3配置webpack-bundle-analyzer插件【推荐】
2019/10/23 Javascript
Vue + Node.js + MongoDB图片上传组件实现图片预览和删除功能详解
2020/04/29 Javascript
[03:09]2014DOTA2国际邀请赛 Mushi前队友送上祝福
2014/07/12 DOTA
python利用beautifulSoup实现爬虫
2014/09/29 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
Python2.7基于笛卡尔积算法实现N个数组的排列组合运算示例
2017/11/23 Python
python数据结构学习之实现线性表的顺序
2018/09/28 Python
selenium+python 对输入框的输入处理方法
2018/10/11 Python
np.newaxis 实现为 numpy.ndarray(多维数组)增加一个轴
2019/11/30 Python
Pytorch 保存模型生成图片方式
2020/01/10 Python
Python Selenium截图功能实现代码
2020/04/26 Python
Python实现列表中非负数保留,负数转化为指定的数值方式
2020/06/04 Python
python中什么是面向对象
2020/06/11 Python
Python中zipfile压缩文件模块的基本使用教程
2020/06/14 Python
心得体会怎么写
2013/12/30 职场文书
主持人演讲稿
2014/05/13 职场文书
贷款委托书怎么写
2014/08/02 职场文书
党员组织生活会发言材料
2014/10/17 职场文书
初二物理教学反思
2016/02/19 职场文书
python使用glob检索文件的操作
2021/05/20 Python
Mysql外键约束的创建与删除的使用
2022/03/03 MySQL