$.extend의 작은 문제

5180 단어
최근에는 모바일을 해왔고, 제이큐리에 익숙한 데다 제퍼토가 제이큐리와 같은 API를 제공해 개발 프레임워크로 택했다.
모바일 단말기 개발이기 때문에 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를 막을 수 있기 때문에 워커로 백엔드에 라인을 만들어서 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가 왜 들어왔는지, 편집기에 있는 $를 봤어.ttend(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
 }


세상에, 정말 이 물건이 이상한 짓을 하고 있구나.in..그래도 else if(source[key]!=undefined) target[key]=source[key] 여기 조건 좀 진지하게 해주면 안 돼요?눈물이 얼굴에 가득 흐르다.
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에 사용자 정의 속성과 방법을 걸어라. 그렇지 않으면 나중에 버그를 찾아야 할 수도 있다.
위에서 말한 것이 바로 본문의 전부이니 여러분들이 좋아해 주시기 바랍니다.

좋은 웹페이지 즐겨찾기