$.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 showModalDialog模态对话框使用说明
Dec 31 Javascript
为jQuery增加join方法的实现代码
Nov 28 Javascript
点击按钮自动加关注的代码(sina微博/QQ空间/人人网/腾讯微博)
Jan 02 Javascript
javascript版的in_array函数(判断数组中是否存在特定值)
May 09 Javascript
基于Jquery插件Uploadify实现实时显示进度条上传图片
Mar 26 Javascript
深入解析Javascript闭包的功能及实现方法
Jul 10 Javascript
关于JavaScript数组你所不知道的3件事
Aug 24 Javascript
不使用 JS 匿名函数理由
Nov 17 Javascript
实例解析Vue.js下载方式及基本概念
May 11 Javascript
9102年webpack4搭建vue项目的方法步骤
Feb 20 Javascript
js实现弹幕飞机效果
Aug 27 Javascript
如何手写一个简易的 Vuex
Oct 10 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
Discuz Uchome ajaxpost小技巧
2011/01/04 PHP
在Yii框架中使用PHP模板引擎Twig的例子
2014/06/13 PHP
php中随机函数mt_rand()与rand()性能对比分析
2014/12/01 PHP
PHP进行批量任务处理不超时的解决方法
2016/07/11 PHP
php版微信公众平台接口参数调试实现判断用户行为的方法
2016/09/23 PHP
php 获取文件行数的方法总结
2016/10/11 PHP
B/S开发中常用javaScript技术与代码
2007/03/09 Javascript
Jquery插件之多图片异步上传
2010/10/20 Javascript
Chrome Form多次提交表单问题的解决方法
2011/05/09 Javascript
JQuery的ON()方法支持的所有事件罗列
2015/02/28 Javascript
深入探秘jquery瀑布流的实现
2016/01/30 Javascript
第一章之初识Bootstrap
2016/04/25 Javascript
jQuery bt气泡实现悬停显示及移开隐藏功能的方法
2016/07/12 Javascript
浅谈React 属性和状态的一些总结
2016/11/21 Javascript
javascript 中模板方法单例的实现方法
2017/10/17 Javascript
Vue表情输入组件 微信face表情组件
2019/02/11 Javascript
详解django模板与vue.js冲突问题
2019/07/07 Javascript
js计算最大公约数和最小公倍数代码实例
2019/09/11 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
详解Vue Cli浏览器兼容性实践
2020/06/08 Javascript
VUE Elemen-ui之穿梭框使用方法详解
2021/01/19 Javascript
[02:27]《DAC最前线》之附加赛征程
2015/01/29 DOTA
python cx_Oracle模块的安装和使用详细介绍
2017/02/13 Python
CentOS下Python3的安装及创建虚拟环境的方法
2018/11/28 Python
Python操作json的方法实例分析
2018/12/06 Python
python之pyqt5通过按钮改变Label的背景颜色方法
2019/06/13 Python
Python批量将图片灰度化的实现代码
2020/04/11 Python
python nohup 实现远程运行不宕机操作
2020/04/16 Python
计算机网络毕业生自荐信
2013/10/01 职场文书
初中生个人学习的自我评价
2013/12/04 职场文书
写给老师的表扬信
2014/01/21 职场文书
大学生创业策划书
2014/02/02 职场文书
高中生逃课检讨书
2014/10/10 职场文书
倡议书作文
2015/01/19 职场文书
社区活动总结
2015/02/04 职场文书
2016年大学生寒假社会实践心得体会
2015/10/09 职场文书