Skip to content

Instantly share code, notes, and snippets.

@think49
Last active October 1, 2017 16:58
Show Gist options
  • Save think49/4296fec9df7ee6a55884bf4d6f600443 to your computer and use it in GitHub Desktop.
Save think49/4296fec9df7ee6a55884bf4d6f600443 to your computer and use it in GitHub Desktop.
string-prototype-includes.js: String.prototype.includes の Polyfill (ECMAScript 2017 準拠)

string-prototype-includes.js

概要

ECMAScript 2015 (ECMA-262 6th Edition) から既定の String.prototype.includes の Polyfill(互換コード)を提供します。 (ES6 で作られたメソッドですが、参考にした仕様は ECMAScript 2017 (ES8) になります。)

使い方

String.prototype.includes( searchString [ , position ] )

第一引数に指定した文字列が含まれていたら、true を返し、含まれなければ false を返します。

console.log('Hello, World!'.includes('Hello')); // true

第二引数で検索を開始するインデックスを指定することが出来ます。

console.log('Hello, World!'.includes('Hello', 1)); // false (index 0 を飛ばして検索する為、HITしません)

第二引数に指定されるインデックス値は整数化して解釈されます。

console.log('Hello, World!'.includes('World', 7.123)); // true
console.log('Hello, World!'.includes('World', 8.123)); // false

第二引数に負の数が指定された場合、0 が指定された場合と同様に扱われます。

console.log('Hello, World!'.includes('Hello', -1)); // true

第一引数に new RegExp を指定することは出来ません。

'Hello, World!'.includes(/Hello/);  // TypeError: First argument to String.prototype.includes must not be a regular expression

String.prototype.includes は故意に汎用的ですが、this 値は null または undefined であってはなりません。

String.prototype.includes.call(null); // TypeError: String.prototype.includes called on null or undefined

参考リンク

/**
* string-prototype-includes-1.0.0.js
* String.prototype.includes Polyfill (ECMA-262, 8th edition / ECMAScript 2017)
*
* @version 1.0.0
* @author think49
* @url https://gist.github.com/think49/4296fec9df7ee6a55884bf4d6f600443
* @license http://www.opensource.org/licenses/mit-license.php (The MIT License)
*/
(function () {
'use strict';
if (typeof this.includes === 'function') {
return;
}
// var toInteger = (function (Number, Infinity, floor, abs) { // 7.1.4 ToInteger ( argument )
// return function toInteger (arg) {
// var number = Number(arg);
// if (number !== number) {
// return 0;
// }
// if (!number || number === Infinity || number === -Infinity) {
// return number;
// }
// return floor(abs(number));
// };
// }(Number, 1/0, Math.floor, Math.abs));
var isRegExp = (function (Object) {
var hasMatch = (function (Symbol, toString) {
if (typeof Symbol === 'function' && typeof Symbol.match === 'symbol') {
return function hasMatch (arg) {
var matcher = arg[Symbol.match];
return typeof matcher !== 'undefined' ? !!matcher : toString.call(arg) === '[object RegExp]';
};
}
return function hasMatch (arg) {
return toString.call(arg) === '[object RegExp]';
};
}(Symbol, Object.prototype.toString));
return function isRegExp (arg) {
return Object(arg) === arg && hasMatch(arg);
};
}(Object));
var includes = (function (String, indexOf) {
return function includes (searchString /* [, position ] */) {
if (this === null || typeof this === 'undefined') {
throw new TypeError('String.prototype.includes called on null or undefined');
}
if (isRegExp(searchString)) {
throw new TypeError('TypeError: First argument to String.prototype.includes must not be a regular expression');
}
return indexOf.call(this, searchString, arguments[1]) !== -1;
};
}(String, String.prototype.indexOf));
if (typeof Object.defineProperties === 'function') {
Object.defineProperties(this, {'includes': {writable: true, enumerable: false, configurable: true, value: includes}});
} else {
this.includes = includes;
}
}.call(String.prototype));
<!DOCTYPE html>
<head>
<title>test</title>
<style>
</style>
</head>
<body>
<script>
'use strict';
String.prototype.includes = null;
</script>
<script src="string-prototype-includes-1.0.0.js"></script>
<script>
'use strict';
console.assert('abcd'.includes('abcd') === true);
console.assert('abcd'.includes('a') === true);
console.assert('abcd'.includes('b') === true);
console.assert('abcd'.includes('d') === true);
console.assert('abcd'.includes('abcde') === false);
console.assert('abcd'.includes('abcd', 0) === true);
console.assert('abcd'.includes('abcd', -1) === true);
console.assert('abcd'.includes('bcd', -1) === true);
console.assert('abcd'.includes('bcd', 1) === true);
console.assert('abcd'.includes('bcd', 2) === false);
Object.defineProperties = null;
</script>
<script src="string-prototype-includes-1.0.0.js"></script>
<script>
'use strict';
console.assert('abcd'.includes('abcd') === true);
console.assert('abcd'.includes('a') === true);
console.assert('abcd'.includes('b') === true);
console.assert('abcd'.includes('d') === true);
console.assert('abcd'.includes('abcde') === false);
console.assert('abcd'.includes('abcd', 0) === true);
console.assert('abcd'.includes('abcd', -1) === true);
console.assert('abcd'.includes('bcd', -1) === true);
console.assert('abcd'.includes('bcd', 1) === true);
console.assert('abcd'.includes('bcd', 2) === false);
</script>
<script>
'use strict';
'Hello, World!'.includes(/Hello/); // TypeError: First argument to String.prototype.includes must not be a regular expression
Symbol = null;
</script>
<script src="string-prototype-includes-1.0.0.js"></script>
<script>
'use strict';
'Hello, World!'.includes(/Hello/); // TypeError: First argument to String.prototype.includes must not be a regular expression
</script>
<script>
'use strict';
String.prototype.includes.call(null); // TypeError: String.prototype.includes called on null or undefined
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment