({}).valueOf.call(myvar)
做什么?
它将任何值转换为对象(对象保持不变,基元转换为包装类型的实例)。
我的问题是如何?有人可以给出更长的答案如何在场景后完成。因为valueOf()
方法意味着返回原始值而不是对象。
console.log{name:"sameer"}.valueOf() //returns an object but cant be displayed since toString() method will be called by js so [object Object] gets displayed which is a string ,how to display the exact return value from valueOf() method .Is there a way?
答案 0 :(得分:3)
回答您的第一个问题
JavaScript有两个主要的变量类别类型,基元和对象。你会经常听到这个,在JS中,一切都是对象。这不完全准确。还有原始数据类型,除了保存值之外什么都不做。
它们没有方法,它们不是包装类型的实例。因此,在您可以调用任何方法之前,需要将它们转换为包装类型的对象。在JavaScript中,此转换是自动的,称为自动装箱。
请允许我演示:
var firstString = "Test";
typeof firstString == "string"; // true
var secondString = new String("Test");
typeof secondString == "string"; // false
secondString.prototype.toString.call// [object String];
注意发生了什么。实际上有两种类型。一个是string
,另一个是[object String]
。这告诉您两件事:secondString instanceof String
是true
。这是一个包装类型。在核心语言中,您看到String
继承自Object
。
但是第一个string
只是一个内存引用,仅此而已。当您调用firstString.replace()
之类的方法时,firstString
会自动转换为其包装类型。这是自动装箱。
以上行为代表以下几对:
号码自动装箱
var x = 5; var y = new Number(5);
,
布尔自动装箱
var x = false; var y = new Boolean(false);
RegExp autoboxing
var x = new RegExp("etc"); var y = /etc/;
<强> Object.prototype.valueOf 强>
为任何对象定义valueOf
方法。为了调用它,它会将所有原始类型转换为它们的包装类型,并保持现有对象不变。现在它只是返回Object引用中保存的值。所以它很简单,它是强制自动运行的一种方式。你正在强迫我之前提到的转换。
回答您的第二个问题
显示未过滤的结果很简单。使用console.dir()
。
看here。
({}).valueOf.call(myvar);
它与Object.prototype.valueOf.call(myVar);
完全相同。现在你已经知道valueOf
做了什么。
假设您知道Function.prototype.call
的工作方式,您的语句会将您传递的对象范围内的valueOf
方法作为this
参数调用Function.prototype.call
(第一个参数是this
对象引用。)
var myvar = {
"name": "name"
};
({}).valueOf.call(myVar);
// is equivalent to
myVar.valueOf();
答案 1 :(得分:3)
您好again!再一次,我们面对强大的对手。在我们开始之前,让我们消除一个错误的想法:
valueOf()方法用于返回原始值而非对象。
不准确。如果传递了原始值,valueOf
将返回一个对象。如果您执行valueOf(object)
,则会获得相同的对象:valueOf(object) === object
。你可以轻而易举地看到:
var obj = {};
obj.valueOf() === obj; //true
现在,对于更有趣的问题:如何定义valueOf
?让我们看看ES5规范以及v8和spidermonkey源。
valueOf
(spec,v8,spidermonkey):
function ObjectValueOf() {
return ToObject(this);
}
正如我们所看到的,它只返回ToObject
,如规范中所定义。兔子洞出现了。
ToObject
(spec,v8,spidermonkey)
function ToObject(x) {
if (IS_STRING(x)) return new $String(x);
if (IS_SYMBOL(x)) return new $Symbol(x);
if (IS_NUMBER(x)) return new $Number(x);
if (IS_BOOLEAN(x)) return new $Boolean(x);
if (IS_NULL_OR_UNDEFINED(x) && !IS_UNDETECTABLE(x)) {
throw %MakeTypeError('null_to_object', []);
}
return x;
}
累积奖金。我们可以在这里看到整个流程。如果它是一个字符串,数字,布尔值等,则返回一个包装器($String
和$Boolean
,而like表示实际的字符串或数字;请参阅here);如果它是一个无效的参数,则抛出一个错误;否则,返回论点。
那个的蜘蛛侠来源深入兔子洞。它定义了ToObject
:
JS_ALWAYS_INLINE JSObject *
ToObject(JSContext *cx, HandleValue vp)
{
if (vp.isObject())
return &vp.toObject();
return ToObjectSlow(cx, vp, false);
}
因此,如果它不是对象,请致电ToObjectSlow
。扣上爱丽丝,会有C ++。我们需要看看ToObejctSlow
做了什么:
JSObject *
js::ToObjectSlow(JSContext *cx, HandleValue val, bool reportScanStack)
{
if (val.isNullOrUndefined()) {
...error throwing magic here...
return NULL;
}
return PrimitiveToObject(cx, val);
}
查看参数是null还是未定义后的更多间接。结局是here:
JSObject *
PrimitiveToObject(JSContext *cx, const Value &v)
{
if (v.isString()) {
Rooted<JSString*> str(cx, v.toString());
return StringObject::create(cx, str);
}
if (v.isNumber())
return NumberObject::create(cx, v.toNumber());
JS_ASSERT(v.isBoolean());
return BooleanObject::create(cx, v.toBoolean());
}
与v8版本几乎相同,只是使用不同的分类法。
现在,正如我之前所说,我认为你的问题更多地与代表你所看到的对象的媒介有关。 Firebug和chrome的devtools不仅仅适合展示一个物体。但是,如果你尝试alert
它,你会看到不幸的[object Object]
,因为这是({}).toString()
给你的东西(因为它会给出[object InternalClassName]
形式的字符串再次,正如我们之前看到的那样。)
作为奖励,请尝试console.dir({foo : 'bar'})