$.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 相关文章推荐
改进版通过Json对象实现深复制的方法
Oct 24 Javascript
event.currentTarget与event.target的区别介绍
Dec 31 Javascript
jquery可见性过滤选择器使用示例
Jun 24 Javascript
无闪烁更新网页内容JS实现
Dec 19 Javascript
javascript中为某个元素指定事件的三种方式
Aug 07 Javascript
javascript字符串对象常用api函数小结(连接,替换,分割,转换等)
Sep 20 Javascript
常用jQuery选择器汇总
Feb 02 Javascript
详解AngularJS2 Http服务
Jun 26 Javascript
webpack 2.x配置reactjs基本开发环境详解
Aug 08 Javascript
VueJS组件之间通过props交互及验证的方式
Sep 04 Javascript
微信小程序实现商城倒计时
Nov 01 Javascript
vue.js中ref和$refs的使用及示例讲解
Aug 14 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 session劫持和防范的方法
2013/11/12 PHP
PHP SPL标准库之数据结构栈(SplStack)介绍
2015/05/12 PHP
Zend Framework框架教程之Zend_Db_Table_Rowset用法实例分析
2016/03/21 PHP
在IE 浏览器中使用 jquery的fadeIn() 效果 英文字符字体加粗
2011/06/02 Javascript
javascript文件中引用依赖的js文件的方法
2014/03/17 Javascript
javascript转换静态图片,增加粒子动画效果
2015/05/28 Javascript
js+css实现文字散开重组动画特效代码分享
2015/08/21 Javascript
javascript中new关键字详解
2015/12/14 Javascript
超实用的JavaScript代码段 附使用方法
2016/05/22 Javascript
JavaScript中双向数据绑定详解
2017/05/03 Javascript
jQuery制作input提示内容(兼容IE8以上)
2017/07/05 jQuery
js实现多张图片延迟加载效果
2017/07/17 Javascript
swiper移动端轮播插件(触碰图片之后停止轮播)
2017/12/28 Javascript
微信小程序中的店铺评分组件及vue中用svg实现的评分显示组件
2018/11/16 Javascript
jQuery实现的点击图片居中放大缩小功能示例
2019/01/16 jQuery
微信小程序 checkbox使用实例解析
2019/09/09 Javascript
js仿360开机效果
2019/12/26 Javascript
jQuery实现动态操作table行
2020/11/23 jQuery
python正则表达式修复网站文章字体不统一的解决方法
2013/02/21 Python
剖析Python的Twisted框架的核心特性
2016/05/25 Python
Python 基础教程之包和类的用法
2017/02/23 Python
Python之pandas读写文件乱码的解决方法
2018/04/20 Python
mac下给python3安装requests库和scrapy库的实例
2018/06/13 Python
Tensorflow的常用矩阵生成方式
2020/01/04 Python
python Pexpect模块的使用
2020/12/25 Python
HTML5 embed标签定义和用法详解
2014/05/09 HTML / CSS
Kipling凯浦林美国官网:世界著名时尚休闲包袋品牌
2016/08/24 全球购物
英国露营设备和户外服装购物网站:Simply Hike
2019/05/05 全球购物
人事主管的岗位职责
2013/11/16 职场文书
县优秀教师事迹材料
2014/01/31 职场文书
设计师个人求职信范文
2014/02/02 职场文书
竞选班长演讲稿500字
2014/08/22 职场文书
2014年财务经理工作总结
2014/12/08 职场文书
深入浅析Redis 集群伸缩原理
2021/05/15 Redis
Feign调用全局异常处理解决方案
2021/06/24 Java/Android
Redis特殊数据类型bitmap位图
2022/06/01 Redis