2015-02-17 10 views
0

В настоящее время я изучаю javascript из окончательного руководства, и многие примеры кода используют xyx.call(undefined,/*args*/) вместо того, чтобы просто вызвать функцию как xyz(/*args*/). Я знаю, что если для исполняемого контекста установлено значение undefined, то значение этого будет относиться к глобальному объекту. Я не могу понять, почему это делается в большинстве примеров, поскольку они не зависят от значений глобального объекта. Может кто-нибудь помочь мне понять разницу.differnce между sum (x, y) vs sum.call (undefined, x, y)

Некоторые реализации Array.protype.reduce

if (!Array.prototype.reduce) { 
     Array.prototype.reduce = function(callbackfn, initialValue) { 
     "use strict"; 
     var O = Object(this), 
     lenValue = O.length, 
     len = lenValue >>> 0, 
     k, 
     accumulator, 
     kPresent, 
     Pk, 
     kValue; 

    if (typeof callbackfn !== 'function') { 
     throw new TypeError(); 
    } 

    if (len === 0 && initialValue === undefined) { 
     throw new TypeError(); 
    } 

    k = 0; 

    if (initialValue !== undefined) { 
     accumulator = initialValue; 
    } else { 
     kPresent = false; 
     while(!kPresent && k < len) { 
      Pk = k.toString(); 
      kPresent = O.hasOwnProperty(Pk); 
      if (kPresent) { 
       accumulator = O[Pk]; 
      } 
      k += 1; 
     } 
     if (!kPresent) { 
      throw new TypeError(); 
     } 
    } 
    while(k < len) { 
     Pk = k.toString(); 
     kPresent = O.hasOwnProperty(Pk); 
     if (kPresent) { 
      kValue = O[Pk]; 
      accumulator = callbackfn.call(undefined, accumulator, kValue, k, O); 
     } 
     k += 1; 
    } 
    return accumulator; 
}; 

}

и некоторые используют:

if (!Array.prototype.reduce) { 
    Array.prototype.reduce = function(callback /*, initialValue*/) { 
    'use strict'; 
     if (this == null) { 
    throw new TypeError('Array.prototype.reduce called on null or undefined'); 
} 
if (typeof callback !== 'function') { 
    throw new TypeError(callback + ' is not a function'); 
} 
var t = Object(this), len = t.length >>> 0, k = 0, value; 
if (arguments.length == 2) { 
    value = arguments[1]; 
} else { 
    while (k < len && ! k in t) { 
    k++; 
    } 
    if (k >= len) { 
    throw new TypeError('Reduce of empty array with no initial value'); 
    } 
    value = t[k++]; 
} 
for (; k < len; k++) { 
    if (k in t) { 
    value = callback(value, t[k], k, t); 
    } 
} 
return value; 

}; }

так что в одном методе функция обратного вызова вызывается с помощью вызова() и в другом осуществлении его не

+2

'call' может сделать немного больше, чем просто контролировать этот контекст. Можете ли вы показать нам, как эта функция используется? – Halcyon

+2

В строгом режиме 'this' будет' undefined', а не 'window', как в' xyx() ', так и' xyx.call() '. – Oriol

+0

@Oriol поэтому зачем использовать оба взаимозаменяемых – Nik6019

ответ

1

JavaScript, является функциональным ОО language.It имеет разный шаблон для вызова функции. xyz(/*args*/) и xyx.call(undefined,/*args*/) - это два разных типа призывов.

xyz(/*args*/) - В этом случае this имеет значение window.

xyx.call(undefined,/*args*/) - В этом случае this будет не чем иным, как контекстом, в котором мы проходим, как в этом случае undefined.

только специальная вещь использования xyx.call(undefined,/*args*/) является то, что у вас есть надежность выбора ваши в функции context call.When вы пишете объектно-ориентированный JavaScript в то время значения context много вопросов. Вот почему более явным является использование xyx.call(undefined,/*args*/) за xyz(/*args*/).

0

Причина, по которой ваши примеры используют вызов функций Array, связана с несколькими (несколько ненужными) типами JavaScript JavaScript.

Как и стандартный тип объекта, который возвращает true на arr instanceof Array, есть также NodeList s, возвращенный из функции document.querySelectorAll, и другие подобные типы. Важно то, что эти другие типы не имеют всех вспомогательных функций Array (reduced, map, forEach).

Однако они все еще имеют все, что им технически необходимо для выполнения этих функций; и метод .call поможет вам это сделать. Итак, допустим, у меня две коллекции.

var arr = [1,2,3]; 
var nodelist = document.querySelectorAll('.baby'); 

arr.map(function(val) { return val + 1; }); // Okay! 
nodelist.map(function(val) { return val.innerHTML; }); // doesn't work 

я могу снять вызов .map на нодлисте с call, придав ему другую цель-объект.

Array.prototype.map.call(nodelist, function...etc) 

// Technically, this works too; just grabbing the method from our arr 
// instance, but it's cleaner to refer to the original 
// type's method. 
arr.map.call(nodelist, function...etc) 

Чтобы объяснить образцы кода, которые вы отправили; это «полиполки» - браузеры должны иметь функцию «уменьшить», но старые браузеры могут не работать. Таким образом, мы сами создаем его для репликации одной и той же функциональности.

+0

Это правда. Но это не объясняет 'xyx.call (undefined)'. – Oriol

+0

@Oriol Hm. На самом деле, я тоже не могу это объяснить; Я думал, что вы просто представляете его в качестве примера, но не заметили, что вы явно сказали, что называют его неопределенным. Честно говоря, даже если технически это минимальное использование ... Я бы просто избегал подобных вещей, как вы можете; он будет убивать читаемость кода. – Katana314

Смежные вопросы