String.prototype.contains = function(str) {
return this.indexOf(str) !== -1;
};
此代码段确实展开了String.prototype
它适用于'foobar'.contains('foo')
等函数调用
但如果它作为一个函数传递,而不是调用它,它就不能很好地工作:
var str = 'foobar';
['foo', 'bar'].every(str.contains);
TypeError: Object [object global] has no method 'indexOf'
我知道你可以这样做:
['foo', 'bar'].every(str.contains.bind(str));
或类似的东西:
['foo', 'bar'].every(function(item) { return str.contains(item); });
但他们只是让我感到尴尬
在我创建的Constructor
函数中,虽然它没有以这种方式工作:
function Foo(myStr) {
this.myStr = myStr;
this.contains = function(fragment) {
return this.myStr.indexOf(fragment) !== -1;
};
}
var someFoo = new Foo('foobar');
['foo', 'bar'].every(someFoo.contains)
TypeError: Cannot call method 'indexOf' of undefined
我可以这样做以使其有效:
function Foo(myStr) {
var self = this; // Line added
this.myStr = myStr;
this.contains = function(fragment) {
return self.myStr.indexOf(fragment) !== -1; // this changed to self
};
}
我想知道是否有扩展String.prototype
的方法,以便我每次使用时都不必将'someString'.contains
绑定到'someString'
作为一个没有调用它的函数。
答案 0 :(得分:2)
试试这个:
Object.defineProperty(String.prototype, "contains", {
get: function () {
return (function(str) {
return this.indexOf(str) !== -1;
}).bind(this);
}
});
它定义了一个带有getter的新属性,这意味着每次你得到"该函数,例如在['foo', 'bar'].every(str.contains);
中,将调用上面定义的函数,并且在这种情况下,该函数的返回值将返回为str.contains
。该函数与您的函数相同,只是我们在getter中绑定this
,这是我们想要的。
如果您的浏览器(或任何使用您的代码的人)未定义Object.defineProperty
,则可以使用__defineGetter__
代替addPropertyWithGetter = function(object, property) {
getter = function () {
return (function(str) {
return this.indexOf(str) !== -1;
}).bind(this);
}
if (_.isFunction(Object.defineProperty)) {
return Object.defineProperty(object, property, {
get: getter,
});
} else {
object.__defineGetter__(property, getter);
}
}
。
完整的解决方案如下所示:
addPropertyWithGetter(String.prototype, "contains")
用法:
{{1}}
答案 1 :(得分:1)
Array.prototype.every()的第二个参数是thisArg
( 在执行回调时使用的值 )。
所以你可以这样做:
['foo', 'bar'].every(str.contains, str);
修复代码:
function Foo(myStr) {
this.contains = function(fragment) {
// myStr is accessible here
return myStr.indexOf(fragment) !== -1;
};
}
var someFoo = new Foo('foobar');
['foo', 'bar'].every(someFoo.contains);