我正在构建一个DSL,这将有利于能够破解一些JS内部.我理解这在一般的JS使用中是一个非常糟糕的主意,但对于我的目的,它没关系.以下代码工作正常:
var str = new String("blah"); str.valueOf = function() { return 10 } console.log(str * 10); // outputs 100
但这不是:
var str = "blah"; str.valueOf = function() { return 10 } console.log(str * 10); // outputs NaN (because str === "blah")
能够理解内部结构的人可以解释一下这里发生了什么吗?这两个例子之间的根本区别是什么?
现在,如果我想更改String原型本身,那么我可以设置所有字符串的valueOf
方法,无论它们何时/何地/如何创建?这可能吗?不幸的是,这似乎不起作用:
String.prototype.valueOf = function() { return 10 } console.log("blah" * 10); // NaN
虽然这样做:
String.prototype.valueOf = function() { return 10 } console.log("blah".valueOf() * 10); // 100
这样做:
String.prototype.valueOf = function() { return 10 } console.log(new String("blah") * 10); // 100
为什么JS引擎对待"blah"
和new String("blah")
不同?谢谢!
顺便说一句,这是一篇很好的文章,有点让我探索这些东西.
当你这样做
var str = "blah";
你正在创建一个字符串原语,但是当你这样做
var str = new String("blah");
你正在调用构造函数并创建一个String 对象.
当你有一个对象时,javascript会valueOf
在尝试使用该对象时在内部调用,其中应该插入一个基元.
对于原语而言,它是相反的,能够链接方法,javascript需要一个对象,并且在原语上new String
调用对象方法时内部基元被包装.
换句话说,当你有一个字符串原语,并且你试图调用时str.valueOf
,javascript将new String(str)
在它调用之前在内部执行valueOf
并返回该值.
但是,当您尝试使用字符串direcly时,您仍然只有原语,并且valueOf
未被调用,则直接插入原始值.
来自MDN
请注意,JavaScript区分
String
对象和原始字符串值.(同样是真实的Boolean
和Numbers
).字符串文字(用双引号或单引号表示)和从
String
非构造函数上下文中调用返回的字符串(即,不使用new
关键字)是原始字符串.JavaScript会自动将基元转换为
String
对象,因此可以将String
对象方法用于基本字符串.在要在原始字符串上调用方法或发生属性查找的上下文中,JavaScript将自动包装字符串原语并调用方法或执行属性查找.