$.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 tools之tooltip
Jul 25 Javascript
Extjs学习笔记之三 extjs form更多的表单项
Jan 07 Javascript
jquery中对表单的基本操作代码
Jul 29 Javascript
jquery中map函数与each函数的区别实例介绍
Jun 23 Javascript
Flexigrid在IE下不显示数据的有效处理方法
Sep 04 Javascript
JavaScript中的标签语句用法分析
Feb 10 Javascript
JS简单判断函数是否存在的方法
Feb 13 Javascript
详解vue-router 2.0 常用基础知识点之router-link
May 10 Javascript
简述jQuery Easyui一些用法
Aug 01 jQuery
vue解决使用webpack打包后keep-alive不生效的方法
Sep 01 Javascript
JavaScript数组去重的方法总结【12种方法,号称史上最全】
Feb 28 Javascript
送你43道JS面试题(收藏)
Jun 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实现读取和编写XML DOM代码
2010/04/07 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
2014/11/19 PHP
PHP调用.NET的WebService 简单实例
2015/03/27 PHP
详解Grunt插件之LiveReload实现页面自动刷新(两种方案)
2015/07/31 PHP
php实现带读写分离功能的MySQL类完整实例
2016/07/28 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
DHTML 中的绝对定位
2006/11/26 Javascript
js 数组操作代码集锦
2009/04/28 Javascript
网络图片延迟加载实现代码 超越jquery控件
2010/03/27 Javascript
由JavaScript技术实现的web小游戏(不含网游)
2010/06/12 Javascript
Node.js模拟浏览器文件上传示例
2014/03/26 Javascript
javascript强制点击广告的方法
2015/02/06 Javascript
JS实现兼容性较好的随屏滚动效果
2015/11/09 Javascript
解析Node.js基于模块和包的代码部署方式
2016/02/16 Javascript
Js删除数组中某一项或几项的几种方法(推荐)
2016/07/27 Javascript
Google Maps基础及实例解析
2016/08/06 Javascript
jQuery实现的右下角广告窗体跟随效果示例
2016/09/16 Javascript
js实现关闭网页出现是否离开提示
2017/12/07 Javascript
Vue-CLI 项目在pycharm中配置方法
2019/08/30 Javascript
[04:44]DOTA2西游记战队视频彩蛋流出 师徒开黑巧遇林书豪
2016/08/03 DOTA
Python统计纯文本文件中英文单词出现个数的方法总结【测试可用】
2018/07/25 Python
Python使用sqlalchemy模块连接数据库操作示例
2019/03/13 Python
django将数组传递给前台模板的方法
2019/08/06 Python
在flask中使用python-dotenv+flask-cli自定义命令(推荐)
2020/01/05 Python
.dcm格式文件软件读取及python处理详解
2020/01/16 Python
python中str内置函数用法总结
2020/12/27 Python
python和opencv构建运动检测器的实现
2021/03/03 Python
马歇尔耳机官网:Marshall Headphones
2020/02/04 全球购物
智能室内花园:Click & Grow
2021/01/29 全球购物
Linux如何为某个操作添加别名
2013/03/01 面试题
超市中秋节活动方案
2014/02/12 职场文书
家长对学生的评语
2014/04/18 职场文书
服务承诺书怎么写
2014/05/24 职场文书
会计专业求职信
2014/08/10 职场文书
升职自荐书
2019/05/09 职场文书