问题
To avoid clobbering existing variables, I have code like this
window.x = typeof x != "undefined" ? x : {}
Which seems like a very long winded way to define something, but necessary to avoid console errors.
I tried this out instead, and it seems to work ok. Is it ok to define a variable like this?
window.x=window.x||{}
Or even in the global scope...
x=this.x||{}
回答1:
If you use this construct:
window.x=window.x||{}
And x
is defined but has a falsy value (zero, the empty string, null, NaN, undefined, and of course false) then that value will be overwritten with a new empty object. If that is acceptable to you because you are confident that x
will either be completely undefined or already defined as an object then sure, go ahead...
回答2:
These are VERY different.
First, without checking for typeof ... === 'undefined'
you will essentially rewrite any 'falsy' values. But that's trivial, there are more subtle nuances.
window.x = typeof x != "undefined" ? x : {}
This will assign value of some x
(not necessary global, it may be a local x
or x
local to some outer function) to global x
(window.x
). When that 'local' x will go out of scope, its value at the moment of assignment will still be stored in window.x
variable.
window.x = window.x || {}
This works with window.x
only; even if we forget at the moment about falsy values, it still does not work the same as the first one (it doesn't even check for 'local' x
existence).
x = this.x || {}
And this one may go completely haywire when this
is volatile (event handlers, timeout functions, to name a few), and will not be allowed within outer functions' body in 'use strict' mode.
回答3:
Here is how to avoid clobbering console.log
specifically:
var console = window.console || {"log": function(){} };
In general, use a dispatch table if you want to avoid the default(||) or ternary(?:) operators:
/* Check for IE Mutation Event */
var browser = "onpropertychange" in document;
/* Map boolean values to variables */
var detect = { "true": ie_param, "false": w3_param };
/* Map string templates with escaped quotes to variables */
var w3_param = [".addEventListener","\u0022DOMAttrModified\u0022",",false"];
var ie_param = [".attachEvent","\u0022onpropertychange\u0022",""];
/* Shadow array indices with key/value pairs */
var api = {"event":0,"attribute":1,"state":2};
/* Generate DOM lookup based on boolean value and matching string template */
var result = "document.getElementsByTagName(\u0022body\u0022)[0]".concat(detect[browser][api.event], "(", detect[browser][api.attribute], ",alert", detect[browser][api.state], ")");
/* Execute generated code */
var lazy = Function(result);
an object that optionally points to an array of elements. The object always has the same number of key/value pairs and each array element always has the same size. Therefore, the array indices can be accessed by name or by value.
References
ECMAScript 2015, Section 19.2.1: The Function Constructor
JavaScript character escape sequences
Character Model for the World Wide Web: String Matching and Searching
Archive of Interesting Code
来源:https://stackoverflow.com/questions/12416385/shortcut-to-existentially-define-variable-in-javascript