Objective
In fact, this section has been talking about the object of this universal data structure in JS. An object can be in a variety of forms, expressed as a difference between a dictionary and an array. More I think this chapter discusses more about the implementation of functions related to the operation, there are possible bugs and how to avoid to fix these bugs. For example, the following is a For...in enumeration property operation, possibly because of some operations on the prototype, resulting in the destruction of data object operations. What to do with the order of attributes, how to handle the array of classes, and so on. Let's look at the main contents of this chapter in a second article. I think there is no need to speak a language, compared to the previous chapters, the individual feel that the content of this chapter is very few, pay attention to a few points, there are just a few emphasis on a knowledge point, a bit cumbersome.
43rd: Construct a lightweight dictionary with a direct instance of object Personal summary
This article focuses on the use of object as a dictionary of this data structure, using a direct instance of object to complete.
The syntax is as follows:
var obj=new Object();//或var obj1={};
The advantage of doing this is that when enumerating the properties of an object, the dictionary is the key value, which can be handled by the for...in loop.
Custom Dictionary class objects
If a custom object is used here when using the for...in loop, the method added to the prototype object is also returned as a key value, which does not match the original program requirements.
Array Object Dictionary
Array objects also have problems with custom class objects, and there are many ES5 array methods that cannot be supported in some environments. The corresponding method is added using Polyfill. Finally, it will contaminate the for...in cycle.
Problems that may arise based on the two methods above. Use direct instances of objects to control possible problems in manageable areas.
Tips
Building a lightweight dictionary with object literals
The lightweight dictionary should be a direct subclass of the Object.prototype so that the for...in cycle is protected from prototype contamination
44th: Use NULL prototypes to prevent prototype contamination personal summary
Based on the previous article, For...in enumeration properties, you can use the Object.create method in ES5 to create an object that is a prototype null. The syntax is as follows:
var obj=Object.create(null);
For environments that do not support the Object.create method, only non-standard attribute __proto__ can be used for compatibility.
var o={__proto__:null};o.instanceof Object;//false
Some people may think of the following form to solve the same problem. But the direct use of c.prototype=null, and can not be completed.
function C(){}C.prototype=null;var c=new C();Object.getPrototypeOf(c) === null;//false
Use NULL as a prototype to prevent prototype contamination, using the following techniques:
Use ES5 's object.create (null) first at development time
Use obj when ES5 is not supported but supports non-standard __proto__ properties. Proto=null;
Other environment hints do not complete the relevant functions
Tips
In a ES5 environment, empty objects created with object.create (null) are less susceptible to contamination.
In some older environments, consider using {__proto__:null}
__PROTO__ is neither standard nor portable, and may no longer be supported in the future
Do not use the key of the __proto__ masterpiece Dictionary because some environments treat it as a special attribute
45th: Use the hasOwnProperty method to avoid the prototype pollution personal summary
43rd, when we talk about the For...in enumeration property in article 44, it has been contaminated by the prototype object and cannot get the properties of the object itself. You can use the hasOwnProperty method to judge your own properties. hasOwnProperty itself is the method in Object.prototype. All objects will continue this method.
Object calls the hasOwnProperty method directly
Using the current object to invoke the hasOwnProperty method directly, one problem is that there is no prototype object in the current object or prototype chain to redefine this method to take care of the correctness of the code.
Using the call method of the function to process the Object.prototype.hasOwnProperty method
var hasOwn=Object.prototype.hasOwnProperty;hasOwn.call(obj1);
It can guarantee the correctness of the hasownproperty when judging the property. The above judgments can be encapsulated in a method for easy invocation for the desired object.
Handling of special attribute __proto__
Use the method of recording State to make code compatible with non-standard properties. Prevent the environment from being different, causing the code functionality to be compromised. For a non-defined default of FALSE, detailed code is viewed in the article.
Tips
Use the hasOwnProperty method to avoid prototype contamination
Using lexical scopes and call methods to avoid overwriting hasownproperty methods
Consider implementing a dictionary operation in a class that encapsulates hasOwnProperty test boilerplate code
Use a dictionary class to avoid using "__proto__" as a key
46th: Use arrays instead of dictionaries to store ordered collections Personal summary
Because the read of the dictionary's properties depends on the for...in loop, and the for...in loop does not specify the order of the related attributes in the standard library, it is not possible to know exactly the order of the property output. If you have strong dependency on the order of attributes, you cannot use a dictionary to store data. With an array store, you can use a for loop to process the data in exactly the order of the indexes.
In this section, it is interesting to mention the calculation of floating-point numbers, the calculation results of floating-point numbers depend on the order of calculation, so it is not possible to use the form of the dictionary is the form of for...in loop to add operations. The solution is to decouple the sequential dependence by converting the floating-point number to an integer and then converting the result of the calculation into a floating-point number.
Tips
Properties that enumerate objects using the for...in loop should be independent of order
If the data in the clustered Operations dictionary ensures that the aggregation operation is independent of the order
Use arrays instead of dictionaries to store ordered collections
47th: Never add enumerable attributes in Object.prototype personal summary
It is also related to the for...in loop, because object is the root object of all JS objects (except object.create (NULL) created). Any object is inherited from the Object.prototype object. The operation on the object.prototype affects all objects. If you do not want to add a method or property, you can use the Object.defineproperty method to set the property or method to be non-enumerable. This avoids contaminating the prototype object.
Tips
Avoid adding attributes to Object.prototype
Consider writing a function instead of a method in Object.prototype
If you do need to add properties to Object.prototype, use the Object.defineproperty method in ES5 to define them as non-enumerable properties.
48th: Avoid modifying objects during enumeration personal summary
is still related to the for...in cycle, as previously mentioned above, the for...in loop cannot guarantee the order of enumerated attributes. Therefore, when modifying object properties, it is possible to enumerate the new property values, possibly enumerating the old property values. Standard rule: If the object being enumerated adds a new attribute during enumeration, the newly added property is not guaranteed to be accessible during enumeration.
Avoid using the for...in loop to perform such operations, using alternative alternatives. For example, you manage loop control and use a while loop to manipulate objects.
This article has related to the traversal of the graph and find the relevant code, to the specific article view.
Tips
When enumerating the properties of an object using the for...in loop, make sure that you do not modify the object
When iterating an object, the application uses a while loop or a classic for loop instead of the for...in loop if the object's contents may be changed during the loop
To be able to predict enumerations in a changing data structure, consider using an ordered data structure, such as an array, instead of using a Dictionary object
49th: Array iterations take precedence over the for loop instead of the for...in loop personal summary for
The For loop guarantees the order in which the code executes and the values that can be determined based on the index. Will not be affected by other factors.
Small knowledge points
The storage of array length can reduce the access of each array length and improve the efficiency of the loop.
for(var i=0;i < arr.length;i++){}
where Var i=0; executes once, I < Arr.length each code block executes before execution, i++ code block executes after execution. So here arr.length every time to get, use the following way better:
for(var i=0,n=arr.length;i < n;i++){}
For...in
The for...in cycle may be contaminated by the object methods in the prototype chain and cannot guarantee the correctness of its code.
Compare:
For loop clear controllable results can be expected
for...in cycle uncertainty, easy to be contaminated, order is not controllable
Tips
Indexed properties of an iterative group should always use a for loop instead of a for...in loop
Consider storing the length of the array in a local variable before the loop to avoid recalculating the array length
50th: Iterative method is better than circular personal summary
Thanks to the powerful, numerous array iterations available in ES5, the array is easier to handle. Mainly including Filter,foreach,every,some,map method, detailed can refer to the corresponding subsection article.
When using a for loop, the boundary condition is often set incorrectly, causing an overflow of the array, or if the array element is not traversed. Be careful to debug and treat these problems, sometimes the code abstraction level is high, the problem is not easy to be found.
Using an iterative approach, there is no need to consider the problem of boundary conditions. The main consideration is the usage of each iteration method and the difference between them. Use different features to fulfill your individual needs.
Add some new iterative methods to the array through the monkey patch, such as the TakeWhile method in this section.
The main function is to extract the first few elements of the array that satisfy the function. Specific code to see in the article.
Tips
Replacing A For loop with an iterative method makes the code more readable and avoids repetitive loop control logic
Use a custom iteration function to abstract common looping patterns that are not supported by the standard library
It is still recommended to use the traditional for loop in case of premature termination. The some and every methods can also be used to exit early
51st: The use of common array methods on class array objects personal summary
In a class array object, the jquery object that you often use is the existence of an array of classes. You can also use the method here to manipulate it. such as using
[].slice.call($(‘a‘)).forEach(function(a){ a.style.display=‘none‘;})
Here are just a few examples where there is a lot of use of iterative methods in jquery.
See how jquery accomplishes the construction of class array objects. Mainly the Makearray method.
//以下代码来自1.7.1版本function makeArray(array,results){ var ret = results || []; if ( array != null ) { var type = jQuery.type( array );//这里只是一个类型的判断 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array );//这里是主要的 } } return ret;}//merge方法function merge( first, second ) { var i = first.length,//并不要求第一个是数组对象,有.length属性就成 j = 0; if ( typeof second.length === "number" ) {//主要关注这里 for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first;}
You can see that the above code jquery itself is an object and does not have an array of elements. Instead, by using the Merge method to add the array elements to the jquery object and to set the length of the long property, the jquery object is transformed into an array of classes.
This can also lead to the two contracts that satisfy the class array:
Has an integer range of 0 to 2^32-1 length property
The length property is greater than the maximum index of the object. An index is an integer in the range of 0 to 2^32-1, whose string representation is a key in the object
Tips
For a class array object, by extracting the method object and using its call method to use the universal array method
Any object that has an indexed property and an appropriate length property can use the universal array method
52nd: The array literal is better than the array constructor personal summary
This is nothing to say, is a variety of corresponding arrays, objects, functions and other constructors, and the literal way, the use of the literal way better.
Prevents the constructor name from being overwritten and does not complete the correct function. Prevents different values from being passed as a result of a parameter. is to literally use literal
Tips
Summarize
The first half of this chapter is about how to solve the object dictionary property enumeration problem. Enumerates the various problems of the for...in loop used by the attribute, the prototype contamination, the order uncertainty, the response problem of the operation during enumeration. The second half mainly discusses the related operation problem of array, the iterative method is better than the loop, the literal is better than the constructor, and the processing method of the class array. By studying this chapter, you can clearly distinguish between the relationships and differences between the dictionary objects and the arrays, and they are also two different data structures. Dictionaries are unordered, hash key-value pairs, arrays are ordered, indexed data sets.
[Effective JavaScript Notes] Chapter 5th: Arrays and dictionaries--personal summary