2015-02-21 3 views
4

На странице MDN String у них есть пример для полифония String.includes.Использование прототипа применительно к этой функции вызова

String.prototype.includes = function() {'use strict'; 
    return String.prototype.indexOf.apply(this, arguments) !== -1; 
}; 

Есть ли причина, что они использовали String.prototype.indexOf.apply против вызова indexOf непосредственно на this?

String.prototype.includes = function(searchString, position) {'use strict'; 
    return this.indexOf(searchString, position) !== -1; 
}; 

ответ

7

Ответ в том, что версия polyfill с помощью this.indexOf не соответствует spec for String.prototype.includes, что позволяет this быть что-нибудь конвертируются в строку:

If searchString appears as a substring of the result of converting this object to a String...

Например, this к includes может стать номер:

<< String.prototype.includes.call(1, '1') 
>> true 

Это аналогично String.prototype.indexOf, который в соответствии с spec также не г equire его this быть строкой.

<< String.prototype.indexOf.call(1, '1') 
>> 0 

Если includes реализуется как ОП предлагает с this.indexOf:

String.prototype.includes = function(searchString, position) {'use strict'; 
    return this.indexOf(searchString, position) !== -1; 
}; 

Затем вызова includes с нестроковой this, как это предусмотрено в спецификации, генерирует ошибку времени выполнения:

<< String.prototype.includes.call(1, '1') 
>> TypeError: undefined is not a function 

Принимая во внимание, что полигон MDN:

String.prototype.includes = function() {'use strict'; 
    return String.prototype.indexOf.apply(this, arguments) !== -1; 
}; 

работает правильно, пользуясь тем, что this для String.prototype.indexOf также не должен быть строкой:

<< String.prototype.includes.call(1, '1') 
>> true 

Так я себе polyfill MDN написан, что путь не для защиты от indexOf метода бытия перезаписывается на каком-то конкретном строковом объекте или в виде стенограммы, чтобы избежать необходимости перечислять параметры или из-за некоторых предпочтений Крокфордиан для идиомы prototype.apply, а скорее для правильной реализации спецификации.

+0

Тогда 'return String (this) .indexOf (searchString, position)! == -1;' будет размещать где * это * не является String и соответствует спецификации. ;-) – RobG

+1

@RobG Не точно, потому что 'String (null') дает вам« null »', и вызов будет «успешным», тогда как 'String.prototype.indexOf.call (null, '1')' генерирует ' String.prototype.indexOf вызвал ошибку с ошибкой null или undefined'. –

+0

Кто положил [* CheckObjectCoercible *] (http://ecma-international.org/ecma-262/5.1/#sec-9.10) там? > :-( – RobG

3

Да, есть основания для этого. Это гарантирует, что даже если свойство строки indexOf было перезаписано, исходное свойство indexOf по-прежнему будет использоваться.

Такое возможно, если мы используем конструктор new String.

var s = new String('test'); 
s.indexOf = function() { 
    throw new Error('this is bad'); 
}; 
s.indexOf('test');//Throws error. 
+3

Не кажется ли это немного странным. Я имею в виду, если вы не можете доверять нормальным методам для строк, массивов и т. Д. ..., то чем вы можете доверять своей среде? Должен ли кто-то идти 'Array.prototype.slice.apply (this, xxx)' просто сделать slice() в массиве? Где останавливается паранойя? – jfriend00

+0

@ jfriend00 Я слышу тебя, но Крокфорд делает этот случай много. Это хороший ответ. – JAAulde

+0

@ jfriend00 Я согласен с тем, что это не самый убедительный случай для использования этого, но полиполк будет использоваться в совершенно неизвестной среде, и цель состоит в том, чтобы максимально точно и безопасно воссоздать функциональность. –

0

String.prototype.indexOf может принимать один или два параметра, а также с помощью применить позволяет просто передать то, что пришли, так как она вошла, не заботясь о проверках типа или присутствия.

+3

ну, вы все равно можете сделать 'this.indexOf.apply (это, аргументы)' –

+0

Конечно, у вас есть точка, хотя я лично ненавижу дублированное использование 'this' в этой строке. Поэтому я ответил, зачем использовать 'apply', но не зачем делать это с' String.prototype'. – JAAulde

+0

Аргумент о 2 аргументах также слабый: 'this.indexOf (searchString, position);' будет гораздо более читаемым, чем заданный '.apply()' call – zerkms

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