我有以下代码:
String.prototype.isLengthGreaterThan = function(limit){
return this.length > limit;
}
console.log("John".isLengthGreaterThan(3));
Number.prototype.isPositive = function(){
return this > 0;
}
console.log(5.isPositive(3)); //error
第一个例子是工作,另一个没有。为什么呢?
根据我的理解,原语不是对象 - 尽管它们可以访问它们的函数构造函数的原型(Number
,String
等)。因此,您可以直接将方法添加到原型中。在上面的例子中,它在一个实例中不起作用。
我正在寻找“引擎盖下”的答案,以了解当你这样做时会发生什么,例如:
var a = 1;
如果它不是一个对象,它如何真正访问它的原型?
答案 0 :(得分:2)
点的东西不是与原语有关,它只是写数字文字的语法。在一个数字中,.
是小数点,而当然不是字符串的情况。要在文字编号上使用方法,您有两种选择:
的括号:
console.log((5).isPositive(3));
两个点(是的,真的):
console.log(5..isPositive(3));
在第二种情况下,它起作用,因为第一个点是小数点;这意味着后面的点不能是小数点,因此它是属性访问器运算符。
如果它不是一个对象,它如何真正访问它的原型。
当您执行权限访问时,它由JavaScript引擎自动提升为对象。在数字的情况下,它就像你打电话给new Number(5)
或类似的一样。对于字符串,它就好像你调用new String("the string")
一样。完成属性访问后,表达式完成后立即丢弃临时对象。当然,JavaScript引擎可以优化对象分配,但从概念上讲,会发生什么。
概念上说:
我们(比方说)var n = 1;
变量a
包含原始数字值1
。
我们n.isPositive(3);
使用Number.prototype.toFixed
从中创建字符串。这是属性访问操作:
引擎评估左侧n
,并获得结果1
(原始数字);这是 base 它将用于属性访问操作。
引擎评估右侧(isPositive
)以确定要查找的属性键(名称)。在这种情况下,它是一个文字,所以关键是字符串"isPositive"
。这是属性访问操作的属性键。
发动机前往基地查找物业。由于我们拥有的基础是原语,因此JavaScript引擎将它(强制它)提升为等效的Number
对象。
由于该对象没有"isPositive"
属性,引擎会查看其原型Number.prototype
并找到它;它是对函数的引用。
发生的各种事情并非真正密切相关,最终isPositive
被调用this
是从原始值1
强制的对象。它发挥作用并产生其回报值。
由于临时对象不再被任何东西引用,因此它有资格进行垃圾回收。
发生这种情况的机制在规范中有点分散:
属性访问器运算符的runtime semantics返回一个称为Reference
规范类型的东西,它基本上是一个纯抽象的规范持有对象,将在以后进行评估。它说基数将是评估属性访问者左侧的结果,属性anme将是评估右侧的结果。
Reference
类型上的GetValue
operation,其中说明(步骤5)如果它是属性引用且基础是原始的,则它通过以下方式强制执行规范' ToObject
操作。
ToObject
,定义了执行此操作的规则。