Exploring JavaScript: SpiderMonkey's quirks

Source: Internet
Author: User
As we all know, the identifier of the name function expression is only valid in the local scope of the function. But

As we all know, the identifier of the name function expression is only valid in the local scope of the function. But what does the local scope of the identifier look like? It is actually very simple. When the name function expression is evaluated, a special object is created. The unique purpose of this object is to save an attribute, and the name of this attribute corresponds to the Function Identifier, the attribute value corresponds to the function. This object will be injected to the front end of the current scope chain. Then, the extended scope chain is used to initialize the function.

Here, there's something interesting at 01:10, that is, the way the ECMA-262 defines this (Save the function identifier) "special" object. In the standard, "like calling the new Object () expression" creates this Object. If you understand this sentence literally, this Object should be an instance of the global Object. However, only one implementation is done according to the standard literal requirement, which is SpiderMonkey. Therefore, in SpiderMonkey, extending Object. prototype may interfere with the local scope of the function:

Object. prototype. x = 'outer'; (function () {var x = 'inner ';/* function foo has a special object in the scope chain -- used to save the identifier of the function. This special object is actually {foo:
 
  
}. When parsing x through the scope chain, the local environment of foo is first parsed. If x is not found, search for the next object in the scope chain. The next object is the object that saves the function identifier -- {foo:
  
   
}, Because the Object inherits from Object. prototype, you can find x here. The value of x is the value of Object. prototype. x (outer ). As a result, the scope of the external function (including the scope of x = 'inner ') will not be parsed. */(Function foo () {alert (x); // The prompt box shows outer })();})();
  
 

However, SpiderMonkey of a later version changes the above behavior, probably because it is considered a security vulnerability. That is to say, "special" objects no longer inherit Object. prototype. However, if you use Firefox 3 or a later version, you can "Review" the behavior.

Another Object that implements an internal Object as a global Object is the Blackberry browser. Currently, its activity Object still inherits Object. prototype. However, the ECMA-262 does not say that the active Object should also be created like calling the new Object () expression (or like creating an Object that saves the NFE identifier ). People's regulations only say that the activity object is a mechanism in the regulations.

Well, let's take a look at the behavior of the BlackBerry Browser:

Object. prototype. x = 'outer '; (function () {var x = 'inner'; (function () {/* resolves x along the scope chain, first, the system searches for the activity objects of a local function. Of course, x cannot be found in this object. However, because the activity Object inherits from Object. prototype, the next Object to search for x is Object. prototype, and Object. prototype does have the definition of x. As a result, the value of x is parsed as -- outer. Similar to the preceding example, the scope (activity object) of the external function containing x = 'inner 'will not be parsed. */Alert (x); // display: outer })();})();

However, the magic is that the variables in the function may even conflict with existing Object. prototype members. Let's take a look at the following code:

(Function () {var constructor = function () {return 1 ;}; (function () {constructor (); // The result is {} (that is, the Object is called. prototype. constructor () instead of 1 constructor === Object. prototype. constructor; // true toString === Object. prototype. toString; // true //...... })();})();

Avoid using attribute names in Object. prototype, such as toString, valueOf, and hasOwnProperty.

JScript Solution

Var fn = (function () {// declare the var f variable of the function to be referenced; // create a named function with conditions // assign its reference to f if (true) {f = function F () {}} else if (false) {f = function F () {}} else {f = function F () {}}// declare a variable corresponding to the function name (identifier) and assign a value of null // This actually marks the function object referenced by the corresponding identifier, // so that the Garbage Collector knows that var F = null can be recycled; // return the return f;} function defined according to the condition ;})();

Finally, we provide an application example that applies the above technology. This is a cross-browser addEvent function code:

// 1) use an independent scope to include the Declaration var addEvent = (function () {var docEl = document.doc umentElement; // 2) Declare the variable var fn to reference the function; if (docEl. addEventListener) {// 3) intentionally give the function a descriptive identifier fn = function addEvent (element, eventName, callback) {element. addEventListener (eventName, callback, false) ;}} else if (docEl. attachEvent) {fn = function addEvent (element, eventName, callback) {element. attachEvent ('on' + eventName, callback) ;}} else {fn = function addEvent (element, eventName, callback) {element ['on' + eventName] = callback ;}} // 4) Clear the addEvent function created by JScript // be sure to use the var keyword before the value assignment // unless addEvent var addEvent = null has been declared at the top of the function; // 5) return fn ;})();
Additional reading

The topic list of this article is as follows:

  1. How should we understand the working principle of the JavaScript engine?
  2. JavaScript exploration: the importance of writing maintainable code
  3. JavaScript exploration: exercise caution when using global variables
  4. JavaScript exploration: var pre-parsing and side effects
  5. JavaScript exploration: for Loop (for Loops)
  6. JavaScript exploration: for-in loop (for-in Loops)
  7. Exploring JavaScript: Prototypes is too powerful
  8. JavaScript: eval () is the devil"
  9. JavaScript exploration: Using parseInt () for Numerical Conversion
  10. Exploring JavaScript: Basic coding specifications
  11. JavaScript exploration: function declaration and function expression
  12. JavaScript exploration: Name function expressions
  13. JavaScript: function name in the debugger
  14. JavaScript: JScript Bug
  15. JavaScript exploration: Memory Management of JScript
  16. Exploring JavaScript: SpiderMonkey's quirks
  17. JavaScript exploration: an alternative solution to naming function expressions
  18. JavaScript exploration: Object
  19. JavaScript exploration: Prototype chain
  20. JavaScript exploration: Constructor
  21. JavaScript probing: executable context Stack
  22. Execution context 1: Variable object and activity object
  23. Execution context 2: Scope chain Scope Chains
  24. Execution context 3: Closure Closures
  25. Execution context 4: This pointer
  26. Exploring JavaScript: Powerful prototype and prototype chain
  27. JavaScript Functions 1: function declaration
  28. JavaScript function 2: function expressions
  29. JavaScript function 3: function expressions in a group
  30. JavaScript function 4: function Constructor
  31. JavaScript variable object 1: VO Declaration
  32. JavaScript variable object 2: VO in different execution contexts
  33. JavaScript variable object 3: two stages of execution Context
  34. JavaScript variable object IV: Variables
  35. Property of the JavaScript variable object __parent _
  36. JavaScript scope chain 1: Scope chain Definition
  37. JavaScript scope chain 2: function Lifecycle
  38. JavaScript scope chain 3: Scope chain features
  39. JavaScript closure 1: Introduction to closures
  40. JavaScript closure 2: Implementation of closure
  41. JavaScript closure 3: Closure usage

This article is available at http://www.nowamagic.net/librarys/veda/detail/1638.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.