Tra*_*vis 25 javascript methods prototype object
警告:创建对本机对象和/或属性的扩展被视为错误形式,并且必然会导致问题.如果您不是仅为您使用的代码,或者您不知道如何正确使用它,请不要使用此代码
我知道你可以使用Object,String,Number,Boolean,等来定义一个方法,是这样的:
String.prototype.myFunction = function(){return this;} //only works on strings.
Run Code Online (Sandbox Code Playgroud)
但我需要做的是在任何值上使用它,并访问函数中的值.
我一派,看着这里,也没有找到什么合适.
2/18/15编辑:如果我使用这个是任何对象的属性,有没有解决方法Object.prototype?
Per Request,这是当前用于的函数isString()
function isString(ins) {
return typeof ins === "string";
}
Run Code Online (Sandbox Code Playgroud)
在几个答案之后,我想出了一些由它引起的代码和错误.
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
Run Code Online (Sandbox Code Playgroud)
Aad*_*hah 14
"点运算符函数"称为方法.在JavaScript中创建可以处理任何数据类型的方法的最简洁方法是创建包装器.例如:
var Wrapper = defclass({
constructor: function (value) {
this.value = value;
},
isString: function () {
return typeof this.value === "string";
},
describe: function () {
if (this.isString()) {
alert('"' + this.value + '" is a string.');
} else {
alert(this.value + " is not a string.");
}
}
});
var n = new Wrapper(Math.PI);
var s = new Wrapper("Hello World!");
n.describe(); // 3.141592653589793 is not a string.
s.describe(); // "Hello World!" is a string.
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}Run Code Online (Sandbox Code Playgroud)
通过创建自己的包装器构造函数,您可以确保:
几个流行的JavaScript库,如下划线和lodash为此目的创建包装器构造函数.
首先,为什么定义Object(或其他内置类型)的属性是不受欢迎的 - 它们出现在意想不到的地方.以下是一些输出一些字符所具有的总英尺数的代码:
var feetMap = {
jerry : 4,
donald : 2,
humpty: 0
}
function countFeet(feetMap) {
var allFeet = 0;
for (var character in feetMap) {
allFeet += feetMap[character];
}
return allFeet;
}
console.log('BEFORE DEFINITION', countFeet(feetMap));
Object.prototype.isString = function() {
return typeof this === "string";
};
console.log('AFTER DEFINITION', countFeet(feetMap));
Run Code Online (Sandbox Code Playgroud)
请注意,如何简单地定义isString函数将影响countFeet函数的结果,该函数现在迭代一个意外的属性.当然,如果迭代是使用hasOwnProperty检查保护的,或者属性被定义为不可枚举,则可以避免这种情况.
避免在内置类型上定义属性的另一个原因是碰撞的可能性.如果每个人都定义了他们自己的isNumber方法,根据用例给出了稍微不同的结果 - 人们可以认为字符串"42"是一个数字而另一个可以说它不是 - 当人们使用多个库时,整个地方都会出现恶意的错误.
现在的问题是-为什么你需要一个方法,可以影响任何值类型?方法应该是它所属的对象类所固有的东西.拥有一个isString方法对Number对象毫无意义 - 它与Numbers没有任何关系.
更有意义的是有一个函数/方法可以返回给它的值的类型作为参数:
var Util = Util || {};
Util.isString(value) {
return typeof value === "string";
}
Util.isString('test') // true
Util.isString(5) // false
Run Code Online (Sandbox Code Playgroud)
你当前代码的原因
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
Run Code Online (Sandbox Code Playgroud)
无法工作是因为当您访问原始值的属性时,JS会创建适当类型的包装器对象,并在该包装器对象上解析该属性(之后它会将其抛出).这是一个应该阐明它的例子:
Object.prototype.getWrapper = function(){
return this;
}
console.log((5).getWrapper()); // Number [[PrimitiveValue]]:5
console.log("42".getWrapper()); // String [[PrimitiveValue]]:"42"
Run Code Online (Sandbox Code Playgroud)
注意,原始值5和对象new Number(5)是不同的概念.
您可以通过返回原始值的类型来改变您的函数.另外,不要忘记使其不可枚举,因此当您遍历随机对象时它不会显示.
Object.defineProperty(Object.prototype, 'isString', {
value : function() {
return typeof this.valueOf() === "string";
},
enumerable : false
});
"5".isString() //returns true
"".isString() //returns true
var str = "string"
str.isString() //returns true
Run Code Online (Sandbox Code Playgroud)
Object.prototype.isString = function() {
return typeof this === "string";
}
"5".isString() //returns false
"".isString() //returns false
var str = "string"
str.isString() //returns false
Run Code Online (Sandbox Code Playgroud)
如果有人可以解释函数是任何对象的属性的解决方法,以及当前方法无法工作的原因,我将提供125个代表.
回答:
好吧,在javascript中,当你调用一个对象的子方法/属性时,
比如"myFunction"(object.myFunction或object ["MyFunction"])
,它将开始查看对象本身是否拥有它.
如果不是:它将遵循原型链(如普通oop中的超类),
直到找到带有方法/属性的"父/超类".
这个原型链的最后一步是Object.
如果Object dosnt具有该方法,则它将返回"undefined".
当您扩展Object类本身时,它总是会查看任何将该方法作为Object调用的对象(在oop中:所有类也是Object,另外还有自己的classtype)这就像在普通OOP中缺少"强制转换"一样.
所以你的函数返回false的原因是它在这个上下文中是一个"对象"而不是"字符串"
尝试使用这个函数:
Object.prototype.typeString = function() {
return typeof this;
}
"5".typeString() //returns "object"
Run Code Online (Sandbox Code Playgroud)
正如大家所说,扩展任何本机JS类是非常糟糕的,但解决方法将从这样的事情开始:
Object.prototype.objectTypeString = function(){
return Object.prototype.toString.call(this);
}
Run Code Online (Sandbox Code Playgroud)
这是一个小提琴:http: //jsfiddle.net/fwLpty10/13/
注意,null dosnt有原型,NaN(Notanumber)被认为是一个数字!!! 这意味着在调用此方法之前,您始终需要检查变量是否为null!
Object.prototype.isString = function(){
return Object.prototype.toString.call(this) === "[object String]";
};
Run Code Online (Sandbox Code Playgroud)
最后的小提琴:http://jsfiddle.net/xwshjk4x/5/
这里的技巧是这个方法返回toString方法的结果,用"this"调用,这意味着在toString方法的上下文中,你调用它的对象是它自己的类(不只是任何超类型)在原型链中)
如果更正,那么扩展Object原型的代码将起作用.
但是,它对this调用方法中的内容做出了错误的假设.使用发布的代码,以下输出是正确的并且是预期的(除了一些旧的实现错误);
"5".isString() //returns false
Run Code Online (Sandbox Code Playgroud)
这是因为JavaScript 在调用方法之前将原始值"包装"或"提升"到相应的对象类型- 实际上是一个String 对象,而不是字符串值.(JavaScript有效地伪造了对原始值的调用方法.)this
将功能替换为:
Object.prototype.isString = function() {
return this instanceof String;
}
Run Code Online (Sandbox Code Playgroud)
然后:
"5".isString() // => true (a string was "promoted" to a String)
(5).isString() // => false (`this` is a Number)
Run Code Online (Sandbox Code Playgroud)
对此的另一个解决方案也是使用多态性; 与修改标准原型相同的"陷阱" 1.
Object.prototype.isString = function () { return false; }
String.prototype.isString = function () { return true; }
Run Code Online (Sandbox Code Playgroud)
1使用defineProperty可以减轻向全局原型添加新的可枚举属性的问题,默认情况下会创建"不可枚举"属性.
简单地改变
x.prototype.y = ..
Run Code Online (Sandbox Code Playgroud)
至
Object.defineProperty(x.prototype, 'y', { value: .. })
Run Code Online (Sandbox Code Playgroud)
(我不是在修改原型的使用;只是解释原始的有问题的输出并指出一种方法来防止枚举行为.)