This is a reading note for In-depth Understanding of ES6
Chapter 1: Block-level scope binding
The var declaration initializes the variable. The declaration can be promoted, but the initialization cannot be promoted.
1. Block-level declaration
let
const
- By default, the code is immutable in a way that reduces the chance of errors
- If a constant is an object, the value in the object can be modified
- Cannot repeat the statement, the statement will not promote
Ii. Temporary Dead Zones:
When the JS engine scans code for variable declarations, it either pushes them to the top of scope (var declarations) or puts them in TDZ (temporary dead zones) (let and const declarations). Accessing variables in TDZ triggers a runtime error. Only after the variable declaration statement has been executed will the variable be removed from the TDZ and then accessible as normal.
The first case:
if(condition) { console.log(typeof value); // Reference error!let value = "blue"; //TDZ
}
Copy the code
The second case:
console.log(typeof value); //'undefined'--> This is not an error, only variables are reported in TDZif(condition) {
let value = "blue";
}
Copy the code
3. Round-robin middle block scope binding
-
Call now (IIFE)
-
Let and const work in for-in and for-of loops because each iteration creates a new binding (const gets an error in the for-loop).
Global block scope binding
Var may inadvertently overwrite an existing global property. Let or const creates a new binding under the global scope, but that binding is not added as a property of the global object. In other words, using let or const does not overwrite a global variable, only overshadows it. Instead of creating properties for global objects, it is much safer to use lets and const.
Note: If you want to define variables under global objects, you can still use var. This is often the case when code is accessed across frames or Windows in a browser.
Chapter 2 strings and regular expressions
Utf-8 code points
Noun explanation:
- Code point: “globally unique identifier, starting from 0” for each character
- Character encoding: The numeric value or code point representing a character is the character encoding of that character.
- BMP (Basic Multilingual Plane)
In UTF-16, the first 2^16 code points are represented as 16-bit coding units. This range is called the basic multilingual plane
CodePointAt (), fromCodePoint() and Normalize ()
- The two methods correspond to charCodeAt() and fromCharCode()
- Normalize (): unification of specifications, for comparison sorting, internationalization.
3. Regular expression u and y modifiers, regular expression copy, and flag properties
- U: encoding unit –> character mode
This method, while effective, is very inefficient when counting the number of code points in a long string. Therefore, you can also use string iterators to solve the problem of inefficiency, and in general, try to reduce the overhead of code point calculations whenever possible.
Detect u modifier support:
function hasRegExpU() {
try {
var pattern = new RegExp('. '.'u');
return true;
} catch (ex) {
return false; }}Copy the code
- Y: If the first match fails, the match is terminated
When performed, the y modifier saves the index that last matched the following character into lastIndexOf; If the result of this operation matches nothing, lastIndexOf is reset to 0. The G modifier behaves similarly.
1. The lastIndex attribute is involved only when methods of regular expression objects such as exec() and test() are called; 2. Methods that call strings, such as match(), do not trigger sticky behavior.Copy the code
- Replication of regular expressions
var re1 = /ab/i; re2 = new RegExp(re1); Re3 = new RegExp(re1,"g"); // There are modifiers (ES6)Copy the code
- Flag property – gets the modifier of the regular expression
The es5 method gets the modifier of the regular expression:
function getFlags(re) {
var text = re.toString();
return text.substring(text.lastIndexOf('/' + 1, text.length);
}
Copy the code
Template literals
Multiline string
Basic string formatting (string placeholders)
HTML escaping
- The label template
functionpassthru(literals, ... Substitutions) {// Return a stringlet result = ""; // Determine the number of cycles to execute based on the number of substitutionsfor(leti=0; i<substitutions.length; i++){ result += literals; Result += substitutions[I] console.log(literals[I]) console.log(substitutions[I])} // Merge the last literal result += literals[literals.length - 1];return result;
}
let count = 10;
price = 0.25;
message = passthru`${count} items cost $${(count * price).toFixed(2)}`;
console.log(message)
Copy the code
- String.raw
String. Raw 'assda\ naadasd' // Code simulationCopy the code
Chapter III Functions
1. Default parameter values
ES5 Default value
What is the problem with the following function??
function makeRequest(url, timeout, callback) {
timeout = timeout || 2000;
callback = callback || function() {};
}
Copy the code
If timeout passes a value of 0, this value is valid, but it is also treated as a false value, and timeout is eventually assigned to 2000. In this case, the safer option is to check the parameter types through typeof, as follows:
functionmakeRequest(url, timeout, callback) { timeout = (typeof timeout ! = ='undefined')? Timeout: 2000; callback = (typeof callback ! = ='undefined')? callback :function() {};
}
Copy the code
ES5 Default value
functionMakeRequest (url, timeout = 2000, callback) {// The rest of the function} At this point null is a valid value, so the default timeout value is not used, i.e. Timeout = null makeRequest('/foo', null, function(body){
doSomething(body);
})
Copy the code
2. Default parameter value pairsarguments
The influence of * *
- ES5:
Non-strict mode: Arguments change and the Arguments object changes accordingly;
Strict mode: The Arguments object no longer changes regardless of how the arguments change;
- ES6
Non-strict mode/strict mode: The Arguments object no longer changes regardless of how the arguments change;
Note: When quoting the default value of a parameter, only the value of the previous parameter can be referenced. That is, the parameter defined first cannot access the parameter defined later. This can be explained by temporary dead zones for default parameters. As follows:
function add(first = second, second) {
returnfirst + second; } console.log(add(1, 1)); //2 console.log(add(undefined, 1))let first = 1;
let second = 1;
//add(undefined, 1)
let first = second;
letsecond = 1; // In a temporary dead zoneCopy the code
3. Restrictions on the use of indefinite parameters
- Each function can declare at most one indefinite argument, and must be placed at the end of all arguments.
- Indefinite parameters cannot be used on object literals
setter
(Because there is one and only one argument to an object literal setter, the number of arguments can be infinite in an indeterminate argument definition)
The Arguments object always contains all the arguments to the function passed in, whether or not an indefinite argument is used.
Expansion operator
letvalue = [25, 50, 75, 100]; //es5 console.log(Math.max.apply(Math, values); //100 //es6 console.log(Math.max(... values)); / / 100Copy the code
5. Name attribute
Two special cases for function names:
- through
bind()
Function creates a function whose name is prefixed with “bound”; - through
Function
The constructor creates a function whose name will be “anonymous”.
var doSomething = function() {// empty function} console.log()doSomething.bind().name); //'bound doSomething'
console.log((new Function()).name); //'Anonymous'
Copy the code
Remember: The value of the function name attribute does not necessarily refer to a variable of the same name. It is just extra information for debugging purposes, so you cannot use the value of the name attribute to get a reference to the function.
Clarify the multiple uses of functions
JS functions have two different internal methods: [[call]] and [[Construct]].
- When a function is called with the new keyword, it executes[[Construct]]Function, which is responsible for creating a new object, usually called an instance, and then executing the function body, will
this
Bind to the instance (yes[[Construct]]The functions of a method are collectively calledThe constructorThe arrow function does not[[Construct]]Methods); - If you don’t pass
new
Executes when the keyword calls a function[[call]]Function, which directly executes the function body in the code;
Metaproperty new.target
To solve the problem of determining whether a function is called by the new keyword, new.target is created (instance of –> new.target).
Using new.target outside of a function is a syntax error.
Block level function
- In ES5 strict mode, an error occurs when a function is declared in a code block.
- In ES6 strict mode, the function can be accessed and called from the block of code that defines it (block-level functions are promoted, let variables are not);
- In ES6 non-strict mode, functions are no longer promoted to the top of a code block, but to the top of a peripheral function or global scope.
Arrow function
Arrow functions differ from traditional JS functions in the following aspects:
- There is no
this
,super
,arguments
andnew.target
Binding; - Can’t pass
new
Key word transfer; - No prototype;
- Can’t be changed
this
The binding; - Does not support
arguments
object - Duplicate named parameters are not supported
Create an empty function:
let doNothing = () => {};
Copy the code
Returns an object literal
let getTempItem = id => ({ id: id, name: "Temp"});
Copy the code
Create a function that executes immediately
let person = ((name) => {
return {
getName: function() {
returnname; }}}) ("xszi")
console.log(person.getName()); //xszi
Copy the code
Arrow function doesn’t have anythis
The binding
let PageHandler = {
id: '123456',
init: function() {
document.addEventListener("click".function(event){ this.doSomething(event.type); // Throw an error},false)},doSomething: function(type) {
console.log("handling " + type + "for" + this.id)
}
}
Copy the code
Use bind() to bind this to PageHandler
let PageHandler = {
id: '123456',
init: function() {
document.addEventListener("click", (function(event){ this.doSomething(event.type); }).bind(this),false)},doSomething: function(type) {
console.log("handling " + type + "for" + this.id)
}
}
Copy the code
Fix with arrow function:
let PageHandler = {
id: '123456',
init: function() {
document.addEventListener("click",
event => this.doSomething(event.type), false);
},
doSomething: function(type) {
console.log("handling " + type + "for" + this.id)
}
}
Copy the code
- Arrow function doesn’t have any
prototype
Properties, it was designed to beUse disposableCannot be used to define new types.- In the arrow function
this
Depends on the non-arrow function outside the functionthis
Value, cannot passcall(), apply()
或bind()
Methods to changethis
The value of the.
Arrow function doesn’t have anyarguments
The binding
Always access the arguments object of the peripheral function
10. Tail call optimization
- In ES5, in the case of circular calls, each unfinished stack frame is kept in memory, which can cause program problems when the call stack becomes too large.
- In ES6, tail-call optimization needs to meet the following three conditions:
- The tail call does not access the variables of the current stack frame (that is, the function is not a closure);
- Inside a function, the tail call is the last statement;
- The result of the last call is returned as a function value;
How to take advantage of tail-call optimization
function factorial(n) {
if ( n<=1 ) {
return1; }}else{// The engine cannot optimize automatically and must perform multiplication after returningreturnn * factorial(n-1); // There is a risk of stack overflow when the stack size increases.Copy the code
function factorial(n, p = 1) {
if ( n<=1 ) {
return1 * p; }}else{
letresult = n * p; // The engine can be automatically optimizedreturnfactorial(n-1, result); // Instead of creating a new stack frame, eliminate and reuse the current stack frame}Copy the code
Chapter 4 Extends object functionality
I. Category of objects
- Ordinary objects
- A specific object
- Standard objects (objects defined in the specification in ES6, such as Array, Date)
- Built-in objects:
Objects that exist in the JS execution environment at the start of script execution, all standard objects are built in.
var person = {
name: 'xszi',
sayName: function() {
console.log(this.name);
}
}
var person = {
name: 'xszi'.sayName() { console.log(this.name); }} // The only difference is that the shorthand can use the super keywordCopy the code
2. Computed Property Name
The property name, represented in square brackets in the object literal, is computable, and its contents will be evaluated and eventually converted to a string.
As follows:
var suffix = ' name';
var person = {
['first' + suffix]: 'xszi'['last' + suffix]: 'wang'
};
console.log(person['first name']); //xszi
console.log(person['last name']) // wang
Copy the code
3. New methods
One of ECMAScript’s design goals is not to create new global functions or new methods on Object.Prototype.
Object.is()
In most cases, object.is () runs the same as ‘===’, except that +0 and -0 are recognized as unequal, and NaN is equivalent to NaN.
Object.assign()
The mixin() method uses the Assignment operator = to copy the properties, but cannot copy the accessor properties to the receiving object, so the added methods discard mixins in favor of assign as the method name.
The object.assign () method can accept any number of source objects and assign attributes to the recipient objects in the specified order. So if multiple source objects have the same attribute, the lower-ranked source object will override the higher-ranked one.
Accessor properties: The object.assign () method cannot assign the accessor properties of the provider to the receiving Object. Because the Object.assign() method performs the assignment operation, the provider’s accessor property is eventually converted to accept a data property in the Object.
eg:
var receiver = {};
supplier = {
get name() {
return 'file.js'}}; Object.assign(receiver, supplier); var descriptor = Object.getOwnPropertyDescriptor(receiver,'name');
console.log(descriptor.value); // 'file.js'
console.log(descriptor.get); // undefined
Copy the code
4. Enumeration order of its own attributes
The basic rules for the enumeration order of your own properties are:
- All numeric keys are sorted in ascending order;
- All string keys are sorted in the order they were added to the object;
- all
symbol
In the order in which they were added.
5. Enhance the prototype of the object
- Change the object’s prototype
Object.setPrototypeOf(targetObject, protoObject);
Copy the code
- Simplified access to prototypes
Super
reference
A Super reference is equivalent to a pointer to an Object’s prototype, which is essentially Object.getProtoTypeof (this). ** must use a Super reference on an Object that uses the shorthand method.
A Super reference is not dynamically variable; it always points to the correct object.
Formal method definition
ES6 formally defines a method as a function that has an internal [[HomeObject]] property to hold the object that the method belongs to.
All references to Super are determined by the [[HomeObject]] property:
- in[[HomeObject]]Call on property
Object.getPrototypeOf()
Method to retrieve a reference to a prototype; - Search for prototypes to find functions with the same name;
- Set up the
this
Bind and call the corresponding method.
Chapter 5 Deconstruction: Make data access easier
1. Object deconstruction
let node = {
type: "Indetifier",
name: "foo"
}
let {type, name} = node;
console.log(type); // Indetifier
console.log(name); // foo
Copy the code
Don’t forget the initializer (the value to the right of the symbol)
var {type, name}; // An error is reportedletConst const const var (const const);letAn initializer is not mandatory, but const is;Copy the code
2. Deconstruct assignment
let node = {
type: "Indetifier",
name: "foo"
}
type = 'Literal', name = 5; // Use destruct syntax to assign values to multiple variables ({type, name} = node); {} is a code block and cannot be placed on the left side of console.log().type); // Indetifier
console.log(name); // foo
Copy the code
- The default values are similar to those in the previous chapter
- Assign values to layout variables that are not of the same name
let node = {
type: "Indetifier",
name: "foo"
}
let { type: localType, name: localName } = node;
console.log(localType); // Indetifier
console.log(localName); // foo
Copy the code
Type: The localType syntax means reading an attribute named type and storing it only in the variable localType.
- Nested object deconstruction
Array deconstruction
- Deconstruction assignment
Array deconstruction can also be used in an assignment context, but does not need to wrap expressions in parentheses, unlike the convention for object deconstruction.
let colors = ['red'.'green'.'blue'], firstColor = 'black', secondColor = 'purple';
[firstColor, secondColor] = colors;
console.log(firstColor); // 'red'
console.log(secondColor); // 'green'
Copy the code
Exchange value
leta = 1, b = 2; [a, b] = [b, a]; console.log(a); //2 console.log(b); / / 1Copy the code
- Nested array deconstruction (address deconstruction assignment)
let colors = ['red'['green'.'lightgreen'].'blue'];
let [firstColor, [secondColor]] = colors;
console.log(firstColor); //red
console.log(secondColor); //green
Copy the code
- Indeterminate element (In a deconstructed array, the indeterminate element must be the last entry; adding a comma after it will cause the program to throw a syntax error)
- Mixed deconstruction (Mixed object and array deconstruction eliminates the need to walk through the entire structure when extracting information from the JSON configuration.)
- Deconstruction parameters
function setCookie(name, value, options) {
options = options || {};
letsecure = options.secure, path = options.path, domian= options.domain, expires = options.expires; // Set the cookie code} // the third parameter maps to optionssetCookie('type'.'js', {
secure: true,
expires: 60000
})
Copy the code
One problem with the above function is that you cannot identify the expected parameters of the function by looking at the declared part of the function. You must read the function body to determine the status of all parameters. This can be optimized using deconstruction parameters:
function setCookie(name, value, {secure, path, domain, Expires}}) {// Set the Cookie code}setCookie('type'.'js',{
secure: true,
expires: 60000
})
Copy the code
- Deconstruction parameters that must be passed;
- Deconstruct the default values of the parameters.
Chapter viSymbol
andSymbol
attribute
Prior to Symbol, all attributes were accessed by attribute names. No matter what elements the attribute names were made of, they were accessed by a string name. Private names were originally designed to allow developers to create non-string names, but normal techniques do not detect private names for these attributes.
throughSymbol
You can add non-string names to attributes, but their privacy is broken.
First, create, useSymbol
,Symbol
Sharing system
- Create and use
let firstName = Symbol();
let person = {};
person[firstName] = 'xszi';
console.log(person[firstName]); //xszi
Copy the code
Because Symbol is a raw value, calling new Symbol() causes the program to throw an error.
The Symbol function takes an optional argument that allows you to add a text description of the Symbol to be created. This description is not available for property access. The Description is stored internally in the [[Description]] property, which can be read only when Symbol’s toString() method is called.
Symbol
Sharing system
Sometimes we might want to share the same Symbol in different code (it is difficult to trace symbols in a large code base or across files), and ES6 provides a global Symbol registry that can be accessed globally, using the symbol.for () method.
let uid = Symbol.for('uid');
let object = {};
object[uid] = '12345';
console.log(object[uid]); //'12345'
console.log(uid); // 'Symbol(uid)'
Copy the code
The Symbol. For () method first searches the global Symbol registry for the existence of the key ‘uid’ Symbol, if so, directly return the existing Symbol; Otherwise, create a new Symbol, register it in the Symbol global registry using this key, and return the newly created Symbol.
You can useSymbol.keyFor()
Methods in theSymbol
Global registry retrieval withSymbol
Student: The bond.
Symbol The global registry is a global-scoped shared environment, meaning you cannot assume which keys exist in the current environment. When using third-party components, use the Symbol key namespace to minimize naming conflicts. Such as jQuery.
Second, Symbol and type forced conversion, attribute retrieval
console.log()
Will be calledSymbol
theString()
methods
desc = String(uid);
desc = uid + ' '; Desc = uid / 2; // Error, cannot be converted to numeric typeCopy the code
- Attribute retrieval
- Object.keys() returns enumerable properties
- Does not consider an enumerable Object. GetOwnPropertyNames (), shall be returned
- Object.getownproperty-symbols () ES6 is used to retrieve the Symbol property of an Object
All objects do not have their own unique attributes at first, but objects can inherit the Symbol attribute from the stereotype chain.
Third, throughwell-know Symbol
Exposed internal operation
Still not how to understand, find a use Symbol of the actual scene to better understand!
Chapter 7 Set Set and Map Set
Set and Map are mainly used in data reorganization and data storage
A Set is a data structure called a collection, and a Map is a data structure called a dictionary
Simulate Set and Map collections with object properties
//set
var set = Object.create(null);
set.foo = true; // Check if the attribute existsif(set.foo){// Code to execute}Copy the code
//map
var map = Object.create(null);
map.foo = "bar"; Var value = map.foo; console.log(value);Copy the code
In general, sets are often used to check for the presence of a key name in an object, while maps are often used to retrieve existing information.
All object property names must be strings, and you must ensure that each key name is string and unique within the object
A Set of
- Ordered - not repeated +0 and -0 are considered equal in a Set. The Set constructor can take all iterable objects as argumentsCopy the code
- Methods in Set: add, has, delete, clear, forEach, size (attribute)
The elements in a Set are not duplicated, so the value can be used as a key. As follows:
let set = new Set([1, 2]);
set.forEach(function(value, key, ownerSet)){
console.log(key + "" + value);
console.log(ownerSet === set);
});
Copy the code
Use this reference in the callback function
let set = new Set([1, 2]);
let processor = {
output(value) {
console.log(value);
},
process(dataSet) {
dataSet.forEach(function(value){ this.output(value); }, this); }}; processor.process(set);
Copy the code
Arrow function this
let set = new Set([1, 2]);
letprocessor = { output(value) { console.log(value); }, process(dataSet) { dataSet.forEach(value => this.output(value)); }}; processor.process(set);
Copy the code
- Convert a Set to an array
let set = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
array = [...set];
console.log(array); //[1, 2, 3, 4, 5]
Copy the code
function eliminbateDuplicates(items){
return [...new Set(items)]
}
let numbers = [1, 2, 3, 3, 3, 4, 5];
noDuplicates = eliminateDuplicates(numbers);
console.log(noDuolicates); //[1, 2, 3, 4, 5]
Copy the code
Weak Set = Weak Set
Fix memory leaks caused by strong references to sets
Weak Set sets store only Weak references to objects and do not store raw values. Weak references in a collection that are unique to an object are reclaimed and freed.
Weak Set methods: add, has, delete
- Weak Set Weak Set
differences | Set | Weak Set |
The biggest difference between | Saves a strong reference to an object value | Holds a weak reference to an object value |
Method passes in non-object parameters | normal | An error |
Can be iterative | Can the iteration | An iterative |
ForEach method is supported | support | Does not support |
Support for size attribute | support | Does not support |
Iv. Map set
- Ordered - key-value pairsCopy the code
In an object, you cannot use an object as a key name for an object property; But in a Map set, you can do that.
letmap = new Map(), key1 = {}, key2 = {}; map.set(key1, 5); map.set(key2, 42); console.log(map.get(key1)); //5 console.log(map.get(key2)); / / 42Copy the code
The above code stores different values in the Map collection using objects key1 and key2 as two key names, respectively. These key names are not cast to anything else, so the two objects are independent of each other in the collection, that is, you can add some additional information to them without modifying the objects themselves.
Map collection methods: set, get, has(key), delete(key), clear, forEach, size(attribute)
Key names of any data type can be accepted during Map collection initialization. To ensure that they are not cast to other data types before being stored in the Map collection, they are placed in an array because this is the only way to render the key name types accurately.
Weak Map sets
Unordered key-value pairs
- Weak reference Map collection. The key in the collection must be an object. If a non-object key is used, an error is reported. - If the value of key name is an object, a strong reference of the object is saved and the garbage collection mechanism is not triggered.Copy the code
- The most important use of Weak maps is to hold DOM elements in Web pages.
let map = new WeakMap(),
element = document.querySelector('.element');
map.set(element, "Original");
let value = map.get(element);
console.log(value); //"Original"/ / remove the element of element element. ParentNode. RemoveChild (element); element = null; // At this time, the Weak Map set is empty and the data is cleared synchronouslyCopy the code
- Weak Map collection method
set, get, has, delete
Private object data
Another application of Weak Map that stores private data for object instances is Weak Map:
var Person = (function(){
var privateData = {},
privateData = 0;
function Person(name){
Object.defineProperty(this, "_id", { value: privateId++ });
privateData[this._id] = {
name: name
};
}
Person.prototype.getName = function() {
return privateData[this._id].name;
}
returnPerson; } ());Copy the code
This method does not know when the object instance is destroyed. Without active management, the data in privateData will never disappear. Weak Map is required to solve this problem.
let Person = (function() {let privateData = new WeakMap(),
privateData = 0;
function Person(name){
privateData.set(this, {name: name});
}
Person.prototype.getName = function() {
return privateData.get(this).name;
}
returnPerson; } ());Copy the code
When choosing between a Weak Map collection and a regular Map collection, the main thing to consider is whether to use only objects as the key name of the collection.
Chapter 8 Iterators and Generators
Iterators are designed to eliminate loop complexity and reduce errors in loops.
What is an iterator?
Iterators are special objects with special ports designed for the iterative process. All iterators have a next() method that returns a result object each time it is called.
The ES5 syntax implements an iterator
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
}
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); //"{ value: 1, done: false}"
console.log(iterator.next()); //"{ value: 2, done: false}"
console.log(iterator.next()); //"{ value: 3, done: false}"
console.log(iterator.next()); //"{ value: undefined, done: true}"
Copy the code
What is a generator?
A generator is a function that returns an iterator, denoted by an asterisk (*) after the function keyword. The new keyword yield is used in the function.
function *createIterator() {
yield 1;
yield 2;
yield 3;
}
letiterator = createIterator(); console.log(iterator.next().value); //1 console.log(iterator.next().value); //2 console.log(iterator.next().value); / / 3Copy the code
yield
Restrictions on the use of
The yield keyword can only be used inside a generator. Using it elsewhere will cause the program to throw a syntax error, even if used inside a generator function. Like the return keyword, the yield keyword does not penetrate function boundaries.
You cannot use arrow functions to create generators
Iterable andfor-of
cycle
Iterables have the Symbol. Iterator property and are objects closely related to iterators. Symbol.iterator returns an iterator to a dependent object using the specified function.
- Checks whether an object is iterable
function isIterable(object) {
return typeof object[Symbol.iterator] === 'function';
}
console.log(isIterable([1, 2, 3])); //true
Copy the code
- Create an iterable
By default, objects defined by developers are non-iterable, but they can be made iterable by adding a generator to symbol. iterator.
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
}
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
console.log(x);
}
1
2
3
Copy the code
4. Built-in iterators
-
Collection object iterator
- entries()
- values()
- keys()
-
String iterator
-
NodeList iterator
Advanced iterator functionality
- Pass arguments to iterators
function *createIterator() {
let first = yield 1;
letsecond = yield first + 2; //4 + 2 yield second + 3; / / 5 + 3}let iterator = createIterator();
console.log(iterator.next()); // '{ value: 1, done: false }'
console.log(iterator.next(4)); // '{ value: 6, done: false }'
console.log(iterator.next(5)); // '{ value: 8, done: false }'
console.log(iterator.next()); // '{ value: undefined, done: true }'
Copy the code
- Throw an error in an iterator
Calling the next() method commands the iterator to continue execution (possibly providing a value), and calling the throw() method also commands the iterator to continue execution, but also throws an error, after which execution depends on the code inside the generator.
- Generator return statement
The expansion operator and for-of loops ignore any return values specified by the return statement and stop reading other values as soon as done becomes true.
- Delegate generator
Delegate two more generators within the generator
- Asynchronous task Execution (******)
The exciting feature of generators has to do with asynchronous programming.
functionRun (taskDef) {// Create an iterator with no restrictionslettask = taskDef(); // Start the taskletresult = task.next(); // Loop the next() functionfunction step() {// Continue if the task is not completedif(! result.done){ result = task.next(); //result = task.next(result.value) step(); }} // Start iterating and execute step(); }Copy the code
Chapter 9 classes in JavaScript
Classes in ES6 are still very different from those in other languages, and the syntax design actually borroys from the dynamic nature of Javascript.
Create a custom type for a near-class structure in ES5:
- First, create a constructor;
- Then, define another method and assign it to the constructor’s prototype.
function PersonType(name) {
this.name = name;
}
PersonType.prototype.sayName = function() {
console.log(this.name);
}
var person = new PersonType('waltz');
person.sayName(); //'waltz'
console.log(person instanceof PersonType); //true
console.log(person instance of Object); //true
Copy the code
Class declaration
- Basic class declaration methods
Class PersonClass {// Equivalent to PersonType constructor(name){this.name = name; } / / equivalent to the PersonType. ProtoType. SayNamesayName() { console.log(this.name); }}let person = new PersonClass('waltz');
person.sayName(); //'waltz'
console.log(person instanceof PersonClass); //true
console.log(person instanceof Object); //true
console.log(typeof PersonClass); //'function'
console.log(typeof PersonClass.prototype.sayName) //'function'
Copy the code
Proprietary properties are properties in the instance, do not appear on the stereotype, and can only be created in the constructor or method of the class. It is recommended that you create all of your own properties in the constructor so that you can control all of your class’s own properties in just one place.
Unlike functions, class attributes cannot be assigned new values.
Why use class syntax
- Function declarations can be promoted, whereas class declarations are not
let
Statement similar, cannot be promoted; They remain in a temporary dead zone until the declaration is actually executed (TDZ). - All code in a class declaration automatically runs in strict mode, and you cannot force code out of strict mode execution.
- In a custom type, you need to pass
Object.defineProperty()
Method manually specifies that a method is not enumerable; In a class, all methods are not enumerable. - Each class has a name called
[[Construct]]
Internal methods called by keyword new that do not contain[[Construct]]
Can cause the program to throw an error. - Use the except keyword
new
Calling the constructor of a class in any other way causes the program to throw an error. - Changing the name of a class in a class results in an error.
Class expression
Similar to declarations and expressions of functions.
In JS engines, class expressions are implemented slightly differently than class declarations. For class declarations, an external binding defined by a let has the same name as an internal binding defined by const. Named class expressions, on the other hand, define names by const and thus can only be used inside the class.
Fourth, as a class of first-class citizens
In the program. A first-class citizen is a value that can be passed into a function, returned from a function, and assigned to a variable. (JS functions are first-class citizens)
function createIbject(classDef) {
return new classDef();
}
let Obj = createObject(class {
sayHi() {
console.log('Hi! ')}}); obj.sayHi(); //'Hi! '
Copy the code
Class expressions can be used in another way, by calling the class constructor immediately to create a singleton. Call the class expression with new, followed by a pair of parentheses:
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('waltz');
person.sayName(); // 'waltz'
Copy the code
This pattern allows you to create singletons using class syntax without exposing class references in scope.
Accessor properties
class CustomHtmlElement() { constructor(element){ this.element = element; } // Create a getter gethtml() {
returnthis.element.innerHTML; } // create the setterset html(value) {
this.element.innnerHTML = value;
}
}
var descriptor = Object.getOwnPropertyDescriptor(CustomHtmlElement.prototype, "html");
console.log("get" in descriptor); //true
console.log("set" in descriptor); //true
console.log(descriptor.enumerable); //false
Copy the code
Name of calculable member
/ / class methodslet methodName = "sayName"; class PersonClass(name) { constructor(name) { this.name = name; } [methodName]() { console.log(this.name); }};let me = new PersonClass("waltz");
me.sayName(); // 'waltz'
Copy the code
Accessor propertieslet propertyName = 'html';
class CustomHTMLElement)() {
constructor(element) {
this.element = element;
}
get [propertyName]() {
return this.element.innerHTML;
}
set[propertyName](value) { this.element.innerHTML = value; }}Copy the code
Seventh, generator method
class MyClass {
*createIterator() { yield 1; yield 2; yield 3; }}let instance = new MyClass();
let iterator = instance.createIterator();
Copy the code
If collections are represented by objects and you want simple methods to iterate over the values in the collection, generator methods come in handy.
While generator methods are useful, it is more useful to define a default iterator for your class if it is intended to represent a collection of values.
Static members
It is a common pattern to emulate static members by adding methods directly to constructors.
functionPersonType(name) { this.name = name; } // Static method persontype.create =function(name) {
returnnew PersonType(name); } / / instance methods PersonType. ProtoType. SayName =function() {
console.log(this.name);
};
var person = PersonType.create('waltz');
Copy the code
Class equivalent:
Class PersonClass {// Equivalent to the PersonType constructor(name) {this.name = name; } / / equivalent to the PersonType. Prototype. SayNamesayName() { console.log(this.name); } // equivalent to persontype. create static create(name) {returnnew PersonClass(name); }}let person = PersonClass.create('waltz');
Copy the code
All methods and accessor properties in a class can be defined with the static keyword. The only limitation is that static cannot be used to define constructor methods.
Static members cannot be accessed from the instance; they must be accessed directly from the class.
Inheritance and derived classes
ES5 implementation
function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
};
function Square(length) {
Rectangle.call(this, length, length);
}
Square.prototype = Object.create(Rectangle.prototype, {
constuctor: {
value: Square,
enumerable: true,
writable: true,
configurable: true}}); var square = new Square(3); console.log(square.getArea()); // 9 console.log(square instanceof Square); //true
console.log(square instanceof Rectangle); true
Copy the code
ES6 class implements
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
returnthis.length * this.width; }} Class Rectangle extends Rectangle {constructor() {// This is equivalent to Retangle. Call (this, length, Rectangle); length) super(length, length); Var square = new square (3); var square = new square (3); console.log(square.getArea()); //9 console.log(square instanceof Square); //true
console.log(square instanceof Rectangle); //true
Copy the code
Tips for using super() :
- Can only be used in constructors of derived classes
super()
, if trying to use a non-derived class (not usingextends
A declared class or a function causes the program to throw an error.- In the constructor
this
Be sure to call it beforesuper()
, which is responsible for initializationthis
, if in callsuper()
Previous attempts to accessthis
Can cause a program error.- If you don’t want to call
super()
, the only way is to make the constructor of the class return an object.
Class method shadowing – methods in a derived class always override methods of the same name in the base class.
Static member inheritance – if the base class has static members, they are also available in derived classes.
Classes derived from expressions — As long as the expression can be parsed into a function and has [[Constructor]] properties and stereotypes, then extends can be used. Extends is powerful enough to make it possible for a class to inherit from any type of expression.
Because you can dynamically determine which base class to use, you can create different inheritance methods
let SerializationMixin = {
serialize() {
returnJSON.stringify(this); }};let AreaMixin = {
getArea() {
returnthis.length * this.width; }};functionmixin(... mixins) { var base =function() {}; Object.assign(base.prototype, ... mixins);return base;
}
class Square extends mixin(AreaMixin, SerializableMixin) {
constructor(length) {
super();
this.length = length;
this.width = length;
}
}
var x = new Square(3);
console.log(x.getArea()); //9
console.log(x.serialize()); // "{'length': 3, 'width': 3}"// If multiple mixin objects have the same attribute, only the last attribute added is retained.Copy the code
Inheritance of built-in objects
Class MyArray extends Array {// null} var colors = new MyArray(); colors[0] ="red";
console.log(colors.length); //1
colors.length = 0;
console.log(colors[0]); //undefined
Copy the code
Symbol.species
attribute
One utility of built-in object inheritance is that a method that originally returns an instance itself in a built-in object will automatically return an instance of a derived class.
Symbol.species is one of many internal symbols that are used to define the static accessor properties of the return function. The function returned is a constructor that must be used whenever an instance of the class is created in the method of the instance (not in the constructor).
In general, whenever you want to call this.constructor from a class method, you should use the symbol.species attribute, allowing the derived class to override the return type. And if you are creating a derived class from a class with a symbol.species attribute defined, be sure to use the value instead of the constructor.
class MyArray extends Array {
static get [Symbol.species]() {
returnArray; }}let items = new MyArray(1, 2, 3, 4),
subitems = items.slice(1, 3);
console.log(items instanceof MyArray); //true
console.log(subitems instanceof Array); //true
console.log(subitems instanceof MyArray); //false
Copy the code
Use in class constructorsnew.target
In the simple case, new.target is equal to the constructor of the class.
Because a class must be called with the new keyword, the new.target attribute is never undefined in the column constructor.
Chapter 10 Improved array functionality
Create an array
1.1 Creating an array before ES6:
- Call the Array constructor
- Use array literal syntax
1.2 ES6:
-
Array.of();
What it does: Helps developers avoid the weird behavior of creating arrays using the Array constructor, because the Array constructor behaves differently from the type and number of arguments passed in.
function createArray(arrayCreator, value){ return arrayCreator(value); } let items = createArray(Array.of, value) Copy the code
-
Array.from();
The ES5 method converts an array of classes to a real array:
function makeArray(arrayLike) { var result = []; for(var i=0, len = arrayLike.length; i<len; i++) { result.push(arrayLike[i]); } return result; } function doSomething() { var args = makeArray(arguments); // use args}Copy the code
Improvement methods:
function makeArray(arrayLike) { return Array.prototype.slice.call(arrayLike); } function doSomething() { var args = makeArray(arguments); // use args}Copy the code
ES6-Array.from():
function doSomething() { var args = Array.from(arguments); // use args}Copy the code
1.3 Mapping and Transformation
If you want to convert an Array further, you can provide a mapping function as the second argument to array.from (), which converts each value in an array-like object into another form and stores the results in the corresponding index of the result Array.
function translate() {
return Array.from(arguments, (value) => value + 1);
}
letnumbers = translate(1, 2, 3); console.log(numbers); / / 2, 3, 4Copy the code
A third argument can also be passed to represent the this value of the mapping function
let helper = {
diff: 1,
add(value) {
returnvalue + this.diff; }};function translate() {
return Array.from(arguments, helper.add, helper);
}
letnumbers = translate(1, 2, 3); console.log(numbers); / / 2, 3, 4Copy the code
Convert iterables with array.from ()
letnumbers = { *[Symbol.iterator]() { yield 1; yield 2; yield 3; }};letnumbers = Array.from(numbers, (value) => value + 1); console.log(numbers2); / / 2, 3, 4Copy the code
If an object is both an Array of classes and iterable, array.from () determines which value to convert based on the iterator.
New methods added for all arrays
2.1 Find () and findIndex() methods
Once the callback returns true, both the find() and findIndex() methods immediately stop searching for the rest of the array.
The indexOf() and lastIndexOf() methods are better choices if you only want to find elements that match a value.
2.2 the fill () method
- Passing a value overrides all the values in the array with that value;
- The second index argument is passed to replace from that index position;
If the start or end index is negative, these values are added to the array’s Length attribute to be the final position.
2.3 copyWith () method
Pass in two parameters, one is the index position to start filling the value and the other is the index position to start copying the value. (If the index has a negative value, it is added to the array’s length property as the final value.)
3. Stereotype array
3.1 define
Stereotyped arrays bring fast transposition to JavaScript. ES6 adopts stereotype arrays as the formal format of the language to ensure better cross-javascript engine compatibility and interoperability with JavaScript arrays.
Stereotyped arrays convert any number into an array of numeric bits.
Stereotyped arrays support storing and manipulating eight different numeric types:
- Signed 8-bit integer (int8)
- Unsigned 8-bit integer (uint8)
- Signed 16-bit integer (int16)
- Unsigned 16-bit integer (uint16)
- Signed 32-bit integer (int32)
- Unsigned 32-bit integer (uint32)
- 32-bit floating point number (float32)
- 64-bit floating-point number (float64)
All of the operations and objects associated with stereotyped arrays are concentrated on these eight data types, but before you can use them, you need to create an array buffer to store the data.
3.2 Array Buffer
An array buffer is the foundation of all stereotyped arrays. It is a memory address that can contain a specific number of bytes. (Similar to C language malloc() allocate memory)
letbuffer = new ArrayBuffer(10); // Allocate 10 bytes console.log(buffer.bytelength); / / 10Copy the code
The actual number of bytes in the array buffer is determined at creation time, and the data in the buffer can be modified, but the size of the buffer cannot be changed.
The DataView type is a generic array buffer view that supports all eight numeric data types.
let buffer = new ArrayBuffer(10),
view = new DataView(buffer);
Copy the code
You can create multiple Views based on the same array buffer, so you can claim a single block of memory for your application, rather than dynamically allocating space when it is needed.
-
Get read attempt information
-
Read/write View information
- Views are independent, and you can read or write data in any format at any time, regardless of how the data was previously stored.
letbuffer = new ArrayBuffer(2), view = new DataView(buffer); view.setInt(0, 5); view.setInt(1, -1); console.log(view.getInt16(0)); // 1535 console.log(view.getInt8(0)); //5 console.log(view.getInt8(1)); / / 1Copy the code
-
Stereotype arrays are views
- ES6 stereotype arrays are actually specific types of views for array buffers, and you can force specific data types. Instead of using generic DataView objects to manipulate array buffers.
- Three ways to create stereotyped arrays.
3.3 Similarities between stereotype array and ordinary array
You can modify the length property to change the size of a regular array, but the length property of a stereotype array is a non-writable property, so you cannot change the size of a stereotype array.
3.4 Differences between stereotyped arrays and ordinary arrays
The most important difference between stereotype arrays and ordinary arrays is that stereotype arrays are not ordinary arrays.
Stereotype arrays also check the validity of the data type. 0 is used instead of all invalid values.
- Additional methods
Set (): Copies other arrays into an existing stereotype array.
Subarray () : Extracts part of the existing stereotype array as a new stereotype array.
Chapter 11, Promise and Asynchronous Programming
Background knowledge of asynchronous programming
JavaScript can either specify what code to execute later, like events and callback functions, or explicitly indicate whether the code executed successfully.
The JavaScript engine can only execute one block of code at a time, so you need to keep track of the code that is about to run, which is placed in a task queue that is added to whenever a piece of code is ready to execute. Whenever a piece of code in the JavaScript engine finishes executing, the next task in the queue is executed by an event loop, a program in the JavaScript engine that oversees the execution of the code and manages the task queue.
Event model –> Callback pattern –>Promise
Ii. Basic knowledge of Promise
Promises are placeholders for the results of asynchronous operations. Instead of subscribing to an event or passing a callback to the target function, the function returns a Promise object. like:
// readFile promises to be completed at some point in the futurelet promise = readFile("example.txt");
Copy the code
When the operation is complete, the Promise goes into two states:
Fulfilled
Promise The asynchronous operation completes successfully;Rejected
The Promise asynchronous operation did not complete successfully due to a programming error or some other reason.
The inner attribute [[PromiseState]] is used to represent three Promise states: “Pending”, “depressing” and “Rejected”. This property is not exposed to the Promise object, so the state of the Promise cannot be detected programmatically, except when the state of the Promise changes, specific actions are taken through the then() method.
If an object implements the above then() method, it is called a Thenable object. All promises are Thenable objects, but not all Thenable objects are promises.
Then method
Catch method (equivalent to passing it only a rejection handler then() method)
/ / refused to promise. Catch (function(err)) {
console.error(err.message);
});
Copy the code
Same as the following call
promise.then(null, function(err)){// Reject console.error(err.message); });Copy the code
Promises work better than events and callbacks
- If events are used, they are not actively triggered when an error is encountered;
- If you use callback functions, you must remember to check for error arguments every time;
- If you don’t add a rejection handler to the Promise, all failures are automatically ignored, so a paragraph should add a rejection handler.
If a Promise is in the processed state, the handler added to the task queue will continue after that.
3. Create unfinished Promises
The Promise executor executes immediately before executing the code in the subsequent flow:
let promise = new Promise(function(resolve, reject){
console.log("Promise");
resolve();
})
console.log("Hi!");
//Promise
//Hi!
Copy the code
Completion handlers and rejection handlers are always added to the end of the task queue after the executor completes.
4. Create handled Promises
-
Using Promise. Resolve ()
-
Using Promise. Reject ()
If a Promise is passed to either the promise.resolve () or promise.reject () methods, the Promise is returned directly.
-
Thenable objects that are not Promises
Both the promise.resolve () and promise.reject () methods can accept non-promise Thenable objects as arguments. If a non-promise Thenable object is passed in, these methods create a new Promise and are called in the then() function.
Non-promise Thenable objects: Ordinary objects that have then() methods and accept resolve and reject.
If you are not sure if an object is a Promise object, you can pass it into either the promise.resolve () method or the promise.object () method based on the expected result. If it is a Promise object, nothing changes.
Five, actuator error
Each executor implies a try-catch block, so the error is caught and passed to the rejection handler.
Six, globalPromise
Refuse to deal with
One of the most controversial issues with promises is that if you reject a Promise without a rejection handler, there is no failure message.
6.1 Rejection processing of node.js Environment
-
unhandledRejection
In an event loop, the event is fired when a Promise is rejected and no rejection handler is provided.
let rejected; process.on("unhandledRejection".function(reason, promise){ console.log(reason.message); // "Explosion!" console.log(rejected === promise); // true }); rejected = Promise.reject(new Error("Explosion!")); Copy the code
-
rejectionHandled
After an event loop, when a Promise is rejected, the rejection handler is called, triggering the event.
let rejected; process.on("rejectionHandled".function(promise){ console.log(rejected === promise); // true }); rejected = Promise.reject(new Error("Explosion!")); // Waiting to add a rejection handlersetTimeout(function(){ rejected.catch(function(value){ console.log(value.message); // "Explosion!" }); }, 1000); Copy the code
6.2 Browser Environment Rejection Processing
-
UnhandledRejection (same description as Node.js)
-
rejectionHandled
The implementation in the browser is almost identical to that in Node.js, where promises and their rejection values are stored in a Map collection and then retrieved in the same way. The only difference is where the information is retrieved in the event handler.
Seven series,Promise
Each time the then() or catch() methods are called, another Promise is actually created and returned, and the second Promise is resolved only when the first Promise is completed or rejected.
Be sure to have a rejection handler at the end of the Promise chain to ensure that all possible errors are handled correctly.
The value returned in the rejection handler can still be used in the completion handler for the next Promise, and if necessary, the entire chain can be resumed even if one Promise fails.
Eight, inPromise
In returnPromise
Returning the Thenable object in a completion or rejection handler does not change the motivation for the Promise executor; the Promise executor defined first executes first, and the Promise executor defined later executes later.
Ix. Multiple responsesPromise
Promise.All()
methodsPromise.race()
methods
Ten,Promise
inheritance
Promises, like any other built-in Promise type, can be derived from other classes as a base class, so you can define your own Promise variables to extend the functionality of built-in promises.
Xi. Based onPromise
To execute asynchronous tasks
let fs = require("fs");
functionRun (taskDef) {// Create an iteratorlettask = taskDef(); // Start the taskletresult = task.next(); // recursive function traversal (function step() {// If there are more tasks to doif(! Result.done) {// Using a Promise to solve the problem simplifies the problemlet promise = Promise.resolve(result.value);
promise.then(function(value) {
result = task.next(value);
step();
}).catch(function(error){ result = task.throw(error); step(); }}}) ()); } // Define a function that can be used by the task executorfunction readFile(filename) {
return new Promise(function(resolve, reject) {
fs.readFile(filename, function(err, contents){
if(err){
reject(err);
}else{ resolve(contents); }}); }); } // Execute a task run(function* () {let contents = yield readFile("config.json");
doSomethingWith(contents);
console.log("done");
})
Copy the code
ES2017 await
Chapter 12, Proxy and Reflection APIS
A Proxy is a wrapper that intercepts and changes the operations of the underlying JavaScript engine, exposing the inner workings of objects in a new language.
I. Agency and reflection
Calling new Proxy() creates a Proxy in place of other target objects, which virtualizes the target so that they appear to function the same.
Proxies can intercept low-level object operations on targets within the JavaScript engine, which, when intercepted, trigger trap functions in response to specific operations.
The reflection API takes the form of a Reflect object, where the default properties of the methods are the same as the underlying operations, which can be overridden by proxies, with each proxy trap corresponding to a Reflect method with the same name and parameters.
Second, the use ofset
Trap validation properties/useget
Trap validates object deconstruction(the Object Shape)
The SET proxy trap intercepts writing properties, and the GET proxy trap intercepts reading properties.
let target = {
name: "target"
}
let proxy = new Proxy(target, {
set(trapTarget, key, value, receiver) {// Ignore existing attributes that you do not want to be affectedif(!trapTarget.hasOwnProperty(key)) {
if(isNaN(value)) {
throw new TypeError("Property must be a number"); }} // Add attributesreturn Reflect.set(trapTarget, key, value, receiver); }}); // Add a new attribute proxy.count = 1; console.log(proxy.count); //1 console.log(target.count); //1 // Since the target already has a name attribute, we can assign proxy.name = to it"proxy";
console.log(proxy.name); //"proxy"
console.log(target.name); //"proxy"
Copy the code
let proxy = new Proxy({},{
get(trapTarget, key, receiver) {
if(! (keyin receiver)) {
throw new TypeError("Properties" + key + "Doesn't exist.");
}
return Reflect.get(trapTarget, key, receiver); }}); // Add an attribute and the program will still run proxy.name ="proxy";
console.log(proxy.name); // "proxy"// If the property does not exist, an error console.log(proxy.nme) is thrown; // Throw an errorCopy the code
Three, use,has
Traps hide existing properties
Four, the use ofdeleteProperty
Traps prevent properties from being deleted
5. Prototype proxy traps
- The operation mechanism of the prototype proxy trap
The prototype proxy trap has some limitations:
getPrototypeOf
Traps must return objects ornull
As long as the return value is bound to cause a runtime error, return value checking can ensure thatObject.getPropertyOf()
Always return the expected value;- in
setPropertyOf
In a trap, if the operation fails, it must returnfalse
At this time,Object.setPrototypeOf()
Will throw an error ifsetPrototypeOf
Returns anything that is notfalse
The value of theta, thenObject.setPrototypeOf()
Assume that the operation succeeds.
- Why are there two sets of methods
Object.getprototypeof () and object.setPrototypeof () are advanced operations that were created for developers to use; The reflect.getProtoTypeof () and reflect.setPrototypeof () methods are low-level operations that give developers access to [[getPrototypeOf]] and [[setPrototypeOf]] permissions that were previously only handled internally.
There are subtle differences in return values between object.setPrototypeof () and reflect.setprototypeof (), with the former returning an Object passed in and the latter returning a Boolean value.
Object extensibility pitfalls
preventExtensions
(Block extension)isExtensible
(Determine whether it is extensible)
The low-level approach has more stringent error checking than the advanced functional approach.
Property descriptor traps
defineProperty
(Defining attributes)getOwnPropertyDescriptor
(Get attributes)
Add a limit to Object.defineProperty()
If you make the trap return true and don’t call the reflect.defineProperty () method, you can silently invalidate the Object.definePropperty() method, which eliminates the error without actually defining the property.
Descriptor object restrictions
When the defineProperty trap is called, descriptor objects have value attributes but no name attributes, because descriptor is not a reference to the third argument actually passed to object.defineProperty (), Instead, a new object contains only those properties that are allowed to be used. The reflect.defineProperty () method also ignores all nonstandard attributes on the descriptor.
Eight,ownKeys
trap
OwnKeys trap implements the default behavior with reflect.ownkeys (), which returns an array containing all of its own key names, including strings and symbols.
Object.getOwnPropertyNames()
Methods andObject.keys()
The result returned by the method willSymbol
The attribute name of the type is excluded.Object.getOwnPropertySymbols()
Method returns results that exclude string attribute names.Object.assign()
Method supports string andSymbol
Two types.
Function proxyapply
andconstruct
trap
Of all the proxy traps, only apply and Construct’s proxy target is a function.
- Validate function parameters
- Don’t have to
new
Calling the constructor
You can determine if the function is called from new by checking the value of the new target.
Let’s say Numbers() is defined in code that you can’t change. You know that your code relies on new Target, and you want the function to avoid checking but still want to call the function. In this case, the behavior when calling with new is already set, so you can only use the Apply trap.
- Overrides the abstract base class constructor
- Callable class constructor
X. Revocable agency
Solve the array problem
- Check array index
- Increases when a new element is added
length
The value of the - To reduce
length
To delete the element
Implement MyArray class
The easiest way to create a class that uses a proxy is to define the class as usual and return a proxy in the constructor so that the object returned when the class is instantiated is the proxy rather than the instance (this in the constructor is the instance).
Use the agent as a prototype
Although it is easy to return a proxy from the class constructor, it also means that a new proxy is created for every instance created. However, there is a way to have all instances share a single proxy: use the proxy as a prototype.
- Use get traps on prototypes
- Use set traps on prototypes
- Use the HAS trap on the prototype
- Use the proxy as a prototype for the class
Chapter 13 encapsulates code with modules
What is a module?
Modules are Javascript code that runs automatically in strict mode and has no way to exit running.
Note: At the top of the module, the value of this is undefined; The module does not support HTML-style code comments.
- Basic syntax for exporting
- Basic syntax for imports
- Importing a single binding
- Import multiple binding imports
The subtle quirks of binding
export var name = "xszi";
export function setName(newName) { name = newName; } // After the import, import {name,setName } from "./example.js";
console.log(name); //xszi
setName("waltz");
console.log(name); //waltz
name = "hahha"; // Throw an errorCopy the code
-
Import and export rename
-
The default value for the module
- Exporting default values
- Import default values
Only one default export value can be set for each module. It is a syntax error to use the default keyword multiple times when exporting.
Use commas to separate the default local name from the non-default value wrapped in braces, and remember that the default value must precede the non-default value in an import statement.
-
Re-export a binding
-
Unbound import
This is a valid module even without any export or import operations.
Unbound imports are most likely to be applied with Pilyfill and Shim created
Shim: is a library that introduces a new API into an old environment, implemented only by means already in the old environment.
Polyfill: A Shim to be used on a browser API. We typically check to see if the current browser supports an API and load the appropriate Polyfill if it doesn’t.
Think of the old browser as a cracked wall, and these polyfills will help us fill in the cracks in that wall.
2. Load modules
-
Use modules in a Web browser
// Load a JavaScript module file <scripttype="module" src="module.js"></script> Copy the code
// Inline import module <scripttype="module"> import { sum } from "./example.js"; let result = sum(1, 2) </script> Copy the code
- Loading order of modules in a Web browser
A module, unlike a script, is unique in that it can use the import keyword to indicate other files that it depends on and that must be loaded into the module to execute correctly. To support this,
Each module can be imported from one or more other modules, which complicates the problem. Therefore, the module is parsed first to identify all import statements; Each import statement then triggers a fetch (from the network or from the cache), and the current module is not executed until all imported resources have been loaded and executed.
- Asynchronous module loading in a Web browser
// There is no guarantee which of the two executes <script firsttype="module" async src="module1.js"></script> <script type="module" async src="module2.js"></script> Copy the code
Load the module as the Worker
Workers can execute JavaScript code outside of the context of a web page.
// Load script.js as a scriptlet worker = new Worker("script.js"); Copy the code
// Load module.js as a modulelet worker = new Worker("module.js", {type: "module"}); Copy the code
A minor change in ECMAScript6
A safe integer
IEEE 754 can only accurately represent integers between -2^53 and 2^53:
var inside = Number.MAX_SAFE_INTEGER,
outside = inside + 1;
console.log(Number.isInteger(inside)); //true
console.log(Number.isSafeInteger(inside)); //true
console.log(Number.isInteger(outside)); //true
console.log(Number.isSafeInteger(outside)); //false
Copy the code
Second, the newMath
methods
Increase the speed of common mathematical calculations
Three,Unicode
identifier
4. Formalization_ptoto_
attribute
In fact, _proto_ is an early implementation of the object.getProtoTypeof () and object.setPrototypeof () methods.
B Understanding ECMAScript 7 (2016)
First, the exponential operator
5 ** 2 == Math.pow(5, 2); //true
Copy the code
Exponentiation operators have the highest precedence of all binary operators in JavaScript (unary operators have precedence over **)
Array.prototype.includes(
The oddity:
Includes () considers +0 and -0 equal, and object.is () recognizes +0 and -0 as different values.
A change in the strict mode of function scope
ECMAScript 2016 disallows the “Use strict” directive in functions where arguments are deconstructed or have default arguments. “Use strict” should only be used in function bodies if the parameters are simple parameter lists that do not contain destructions or default values.