Some understanding of JavaScript

Source: Internet
Author: User
Tags closure function definition

Recently read the "Nodejs Development Guide" found that Nodejs in some specific areas by his own strengths, suitable for dense computing but the business logic is relatively simple scenario, if you do the site or choose PHP Bar, hehe, this book I in addition to the 5th chapter "with the Nodejs development of the Web" did not see, Other chapters are probably finished, understand the simple use of nodejs, feel that the most important to me is the Appendix A "Advanced Features of JavaScript", here the content let me have a deep understanding of JS advanced features, the following is a record:

First, scope

Unlike common languages such as C, C + +, and Java, the scope ofJavaScript is not a block-level scope surrounded by curly braces (block scope), a feature that is often overlooked by most people and leads to inexplicable errors. For example, the following code, in most of the language of Class C, the variable undefined error, but in JavaScript is completely legal:

if (true) {var somevar = ' value ';} console.log (Somevar); Output value

This is because the scope of the JavaScript is entirely determined by the function, and the curly brackets in the IF, for statements are not separate scopes.

1. Function scope

Unlike most languages of Class C, a block of code enclosed by a pair of curly braces is a scope, and the scope of JavaScript is defined by functions, and variables defined in a function are only visible inside the function, which we call function scopes. When a variable is referenced in a function, JavaScript searches for the current function scope, or local scope, and searches its upper-level scope until it is found , up to the global scope . Let's look at a simple example:



The above example is very clear, the function definition of JavaScript can be nested, each layer is a scope, the variable search order is from inside to outside . The following example may be somewhat confusing:

This is a feature of JavaScript, in terms of scope search order, when the Console.log function accesses the scope variable,JavaScript searches for the scope of the function f, it happens to search the scope variable in the F-scope , so Scope defined in the upper scope is masked , but when executed to the Console.log statement, scope isnot defined , or initialized, so the undefined value is obtained.

The nested relationship of a function scope is determined at the time of the definition , not when it is called, that is, the scope of the JavaScript is a static scope, also called the lexical scope, because the nested relationship of the scope can be determined at the time of parsing, Instead of having to wait for the runtime to determine. The following example illustrates all of this:

var scope = ' top '; var f1 = function () {console.log (scope);};
F1 (); Output Top
var F2 = function () {var scope = ' F2 '; F1 (); }; F2 (); Output to

In this example, the F1 called by F2, when looking for the scope definition, finds the scope variable defined in the parent scope instead of the scope variable defined in the F2. This indicates that the nested relationship of the scope is not in the calling
Determined at the time of definition.

2. Global scope

In JavaScript, there is a special object called a global object. This object in node. js corresponds to the Global object, which corresponds to the Window object in the browser. Because all properties of a global object are visible everywhere, this object is also called the global scope. Variables in the global scope can be directly referenced in any function, without having to pass through the global object.
Variables that meet the following conditions belong to the global scope:
? Variables defined at the outermost layer;
? The properties of the global object;
? Implicitly defined variables anywhere (variables that are directly assigned are not defined).
It is important to note that 3rd, implicitly defined variables are defined in the global scope, that is, variables that are directly assigned without a VAR declaration . This is often forgotten, and one of the important principles of modular programming is to avoid using global variables, so we should not implicitly define variables anywhere.

Second, closed package

1, what is called closures

Closures are strictly defined as "aggregates of functions (environments) and their enclosing free variables." "In layman's words, every function in JavaScript is a closed-packet

When a function returns a function that is defined internally , a closure is generated, and the closure includes not only the returned function , but also the defined environment of the function. In the above example, when the inner function of the function generateclosure () is referenced by an external variable counter, the local variable of counter and Generateclosure () is a closure

Counter1 and Counter2 call the Generate-closure () function respectively, generating two instances of closures, which are internally referenced by the count variable belonging to their respective operating environment. We can understand that, when generateclosure () returns a Get function, the internal variable (that is, the count variable) of the Generateclosure () function that the get may refer to is returned privately, and a copy is generated in memory. Then Generateclosure () returns two instances of the function Counter1 and Counter2 are independent of each other.

2, the use of closures

1), nested callback functions

The following code is the use of MongoDB in node. js to achieve a simple increase in user functionality:

Exports.add_user = function (User_info, callback) {Varuid = parseint (user_info[' uid ']);         Mongodb.open (err, db) {if (err) {callback (err); return;}             Db.collection (' Users ', function (err, collection) {if (err) {callback (err); return;}                 Collection.ensureindex ("UID", function (Err) {if (err) {callback (err); return;}                     Collection.ensureindex ("username", function (Err) {if (err) {callback (err); return;}                             Collection.findone ({Uid:uid}, function (err) {if (err) {callback (err); return;}                             if (DOC) {callback (' occupied ');                                 } else{Varuser = {Uid:uid,                             User:user_info,};              Collection.insert (user, function (err) {               Callback (ERR);                     });                 }                     });             });         });     }); });  };

This code is nested in the layers of closures, and each layer is nested in a callback function. The callback function does not execute immediately, but waits for the requested function callback after the corresponding request is processed. As we can see, there is a reference to callback in each layer of nesting, and the innermost definition of the UID variable is also used. Due to the existence of the closure mechanism, even if the outer function has been executed, the variable requested in its scope will not be released, because the inner layer function may refer to these variables, which makes it possible to implement nested asynchronous callbacks perfectly.

2), implementing private members

JavaScript objects do not have private properties, which means that each property of an object is exposed to the outside. This can be a security risk, such as the object's users directly modify a property, resulting in the consistency of the internal data of the object is destroyed, and so on. JavaScript uses a convention to underline all private attributes (for example, _myprivateprop), indicating that the property is private and that the external object should not read and write directly to it. But this is only an informal agreement, assuming that the object's users do not do so, there is no more stringent mechanism? The answer is yes, it can be achieved by closures.

Only call counter () to access the count variable within the closure and increase it by 1 according to the rules, it is never possible to find the count variable in any other way. Inspired by this simple example, we can encapsulate an object with a closure and return only an object with an "accessor" to hide the details.

Third, the object

1. Creation and access of objects

An object in JavaScript is actually an associative array of properties consisting of names and values, the type of the value can be any data type, or functions and other objects

In JavaScript, you can create a simple object in the following ways:

var foo = {}; You can also use this var foo = new Object () to explicitly create an object.

We can also create objects using the pattern of associative arrays, which are modified to:

2. Call and apply

The function of call and apply is to invoke a function with a different object as the context. In short, a member function that allows an object to invoke another object

The function of call and apply is consistent, and the subtle difference between calls takes the parameters of the called function in the parameter table, and apply takes an array to accept the parameters of the called function. The syntax for call and apply are:
Func.call (thisarg[, arg1[, arg2[, ...])
Func.apply (thisarg[, Argsarray])


3. Prototypes



The code above uses a prototype instead of a constructor to initialize the object. What is the difference between doing this and defining attributes directly within the constructor?

? the properties that are defined within the constructor are inherited differently from the prototype, and the child object needs to explicitly call the parent object to inherit the properties defined within the constructor.
? Any properties defined within the constructor, including functions, are created repeatedly, and the two objects produced by the same constructor do not share the instance.
? functions defined within a constructor have the overhead of a run-time closure, because local variables within the constructor are also visible to the functions defined therein.



var foo1 = Newfoo (); var foo2 = Newfoo (); Console.log (foo1.func1 = = foo2.func1); Output False Console.log (Foo1.func2 = = FOO2.FUNC2); Output true

So when do we use prototypes, and when do we use constructor definitions to create properties?

? unless you have to use a constructor to close the package, define member functions with prototypes as much as possible, because it reduces overhead.
? Try to define a generic member within a constructor, especially an object or an array, because the members defined by the prototype are shared by multiple instances.

4. Prototype chain

There are two special objects in JavaScript: Object and function, which are constructors that are used to generate objects. Object.prototype is the ancestor of all objects, Function.prototype is the original of all functions
types, including constructors, I divide the objects in JavaScript into three categories, one is user-created objects , one is a constructor object , and the other is a prototype object.

A user-created object, that is, an object explicitly constructed with the new statement in a general sense. A constructor object refers to a normal constructor, which is a function that generates a normal object through new calls. The prototype object refers specifically to the object that the constructor prototype property points to. Each of these three types of objects has a __proto__ property that points to the prototype of the object, which can be traced back to the Object.prototype from any object along which it begins to traverse. The constructor object has the prototype property, which points to a prototype object that, when created with the constructor, will point to the prototype property of the constructor when the object is created by the __proto__ property. The prototype object has the constructor property, which points to its corresponding constructor.



  

In JavaScript, inheritance relies on a set of mechanisms called the prototype chain (prototype chain). The essence of attribute inheritance is that an object can access the properties of any prototype object on its prototype chain. For example, the Foo object in the example above has foo. __proto__ and Foo. __proto__.__proto__ a shallow copy of all attributes (only the base data type is copied, not the object). So you can access foo.constructor directly from Foo.
__proto__, Foo.prototype), foo.tostring (from Foo. __proto__.__proto__, or Object.prototype).

5. Replication of objects

JavaScript and Java do not have the same pointer as the C language, all object types of variables are reference to the object, the assignment of a value between two variables to pass an object does not copy the object , but just pass the reference , Sometimes we need to copy an object completely, how do we do it? There is a clone method in the Java language that enables object replication, but there is no such function in JavaScript. So we need to implement such a function manually, and one simple way is to copy all the properties of the object:

To write your own clone method





Console.log (Obj.likes); Output [' node ', ' Python '] console.log (newobj.likes); Output [' node ', ' Python ']

The above code is an implementation of a shallow copy of an object (shallowcopy), which copies only the properties of the base type , and the properties of the shared object type . The problem with shallow copy is that two objects share object type properties, and shallow copy is a property of two object-shared object types, such as the likes attribute in the previous example points to the same array.

Implementing a full copy, or deep copy, is not an easy task because there are many different objects in addition to the basic data types, and there are complex structures inside the object, so it needs to be done recursively:

Object.prototype.clone = function () {var newObj = {}; for (var i) {if (typeof (This[i]) = = ' object ' | | typeof (This[i]) = = ' function ') {newobj[i] = This[i].clon     E ();     } else{Newobj[i] = this[i]; }} return NEWOBJ; };
Array.prototype.clone = function () {var newarray = []; for (var i = 0; i < this.length; i++) {if (typeof (This[i]) = = ' object ' | | typeof (This[i]) = = ' function ') {NEW     Array[i] = This[i].clone ();     } else{Newarray[i] = this[i]; }} return NewArray; };

Function.prototype.clone = function () {var = this;   var newfunc = function () {returnthat.apply (this, arguments);   };   for (var i, this) {newfunc[i] = this[i]; } Returnnewfunc; };
var obj = {name: ' byvoid ', likes: [' node '], Display:function () {console.log (this.name); }, };
var newObj = Obj.clone (); NewObj.likes.push (' Python '); Console.log (Obj.likes); Output [' node '] Console.log (newobj.likes); Output [' node ', ' Python '] console.log (newobj.display = = Obj.display); Output false
from: http://www.cnblogs.com/whoamme/p/3492467.html

Some understanding of JavaScript

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.