admin管理员组

文章数量:1416314

On the MDN String page they have an example to polyfill String.includes.

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

Is there a reason they used String.prototype.indexOf.apply vs calling indexOf directly on this?

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

On the MDN String page they have an example to polyfill String.includes.

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

Is there a reason they used String.prototype.indexOf.apply vs calling indexOf directly on this?

String.prototype.includes = function(searchString, position) {'use strict';
    return this.indexOf(searchString, position) !== -1;
};
Share Improve this question edited Feb 21, 2015 at 6:06 JAAulde 19.6k5 gold badges56 silver badges64 bronze badges asked Feb 21, 2015 at 6:04 Eric MajerusEric Majerus 1,2383 gold badges15 silver badges23 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 7

The answer is that the version of the polyfill using this.indexOf would not conform to the spec for String.prototype.includes, which allows this to be anything convertible to a string:

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

For instance, the this to includes could be a number:

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

This is analogous to String.prototype.indexOf, which according to spec also does not require its this to be a string.

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

If includes is implemented as the OP suggests with this.indexOf:

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

Then calling includes with a non-string this, as allowed by the spec, generates a run-time error:

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

Whereas the MDN polyfill:

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

works correctly, taking advantage of the fact that the this for String.prototype.indexOf also need not be a string:

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

So I imagine the MDN polyfill is written that way not to protect against the indexOf method being overwritten on some particular string object, or as a shorthand to avoid having to list out parameters, or due to some Crockfordian preference for the prototype.apply idiom, but rather in order to correctly implement the spec.

Yes, there is a reason to do this. It ensures that even if the indexOf property of the string has been overwritten, the original indexOf property will still be used.

Such a thing is possible if we use the new String constructor.

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

String.prototype.indexOfcan take one or two parameters, and using apply allows you to simply pass along what came in, as it came in, without worrying about type or presence checks.

本文标签: javascriptUsing prototype apply vs this to call functionStack Overflow