How to understand if (name in {}) in javascript?
I encounter a js function snippet, list as follows
each = function(obj, fun) {
if (typeof fun != "function") {
return obj
}
if (obj) {
var return_value;
if (obj.length === undefined) {
for (var name in obj) {
if (name in {}) { // how to undertand this line, what's purpose?
continue
}
return_value = fun.call(obj[name], obj[name], name);
if (return_value == "break") {
break
}
}
} else {
for (var i = 0,
length = obj.length; i < length; i++) {
开发者_StackOverflow return_value = fun.call(obj[i], obj[i], i);
if (return_value == "break") {
break
}
}
}
}
return obj
};
Thanks for your answer:)
What it's doing is seeing if that property name exists in a blank object. So for instance, it will filter out toString
(on implementations that aren't buggy about toString
and in
; IE is).
It may be an attempt to work around people adding things to the Object.prototype
(which is a very, very bad idea). For instance:
Object.prototype.foo = "bar"; // <== VERY BAD IDEA
alert({}.foo); // alerts "bar"
function Thingy(a, b) {
this.a = a;
this.b = b;
}
Thingy.prototype.x = 42;
var t = new Thingy(1, 2);
If I want to copy t
, including its inherited x
property from Thingy
but not including the foo
property it inherits from Object
, I could use that if (name in {})
to skip those.
Mind you, it's not a very smart way to do that, as it will fail if I do this:
var t = new Thingy(1, 2);
t.foo = "charlie";
Now t
has its own foo
, which presumably I would have wanted to copy.
A more thorough check would be:
dest = {};
blank = {}; // No need to recreate it on every iteration
for (name in src) {
if (src.hasOwnProperty(name) || !(name in blank)) {
dest[name] = src[name];
}
}
That will only filter out ones that are inherited, or at least might be inherited, from Object
. But even that's flawed; what if it inherits a value for the property, but not the value from Object
(e.g., something in the middle — Thingy
perhaps — has overridden Object
's default)?
So you may want to refactor this code you've inherited, probably in terms of using hasOwnProperty
and making sure that nothing anywhere in your application puts things on Object.prototype
.
The in
operator returns true if there is a property in the second operand with the identifier of the first operant, and false otherwise. So name in {}
checks whether there is a property with the name of the value of name
.
This probably seems odd as {}
does not seem to have any properties. But a plain object inherits some the properties from Object.prototype. So "toString" in {}
returns true as there is Object.prototype.toString
. There is also the hasOwnProperty
method inherited from Object.prototype.hasOwnProperty
that can be used instead.
In is a special operator that returns true if the specified property is in the specified object.
From https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special_Operators/in_Operator
Every object, including {}, inherits properties from Object.prototype. The if
here makes the loop continue if name
is one of those inherited properties.
Example: console.log('toString' in {});
logs true
. console.log('customProperty' in {});
logs false.
精彩评论