程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> $.extend 的一個小問題

$.extend 的一個小問題

編輯:更多關於編程

       本文給大家記錄的是個人在使用$.extend 的時候遇到的一個小問題,以及原因分析和解決方案,十分的實用,有需要的小伙伴可以參考下。

      最近一直在搞移動端,也由於自己對jQuery比較熟悉,再加上Zepto提供了跟jQuery一樣的API,所以就選擇了Zepto作為開發框架。

      由於是移動端開發,所以也應用了一些ES5新增的API,比如forEach,下面就是我寫的代碼的一些示例:

      ?

      1

      2

      3list.forEach(function(v) {

      return !!v;

      })

      我天真的以為forEach就跟jQuery的each一樣,只要我的返回值為false,它就會中斷循環,於是,類似這樣的遍歷代碼寫了不少(真的是懶得為每個遍歷去聲明變量啊)

      寫了一段時間之後我突然發現,forEach的回調函數並不能中斷循環,於是,我便在Array.prototype上面掛了個函數,然後replaceAll,完美。

      ?

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10Array.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的源碼:

      ?

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23function 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投訴,希望它能安慰我一下,沒想到:

      ?

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63jQuery.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了。

      以上所述就是本文的全部內容了,希望大家能夠喜歡。

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved