globalThisThe top-level object

The JavaScript language has a top-level object that provides the global environment (the global scope) in which all code is run. However, top-level objects are not uniform across implementations. In the browser context it refers to the Window object and in Node it refers to the Global object. In ES5, properties of top-level objects are equivalent to global variables.

var a = 2;
window.a / / 2
Copy the code

ES6 changes this by specifying, on the one hand, that global variables declared by var and function commands remain properties of top-level objects for compatibility purposes. On the other hand, global variables declared by let, const, and class commands are not properties of top-level objects. That is, starting with ES6, global variables will gradually decouple from the properties of top-level objects.

var a = 2;
window.a / / 2

let b = 3
window.b //undefined
Copy the code
  • In the browser, the top level object iswindow, butNodeWeb WorkerThere is nowindow.
  • The browser andWeb WorkerInside,selfIt also points to the top level object, butNodeThere is noself.
  • NodeInside, the top level object isglobal, but no other environment supports it.

ES2020 introduces globalThis as a top-level object at the language standard level. In other words, any environment where globalThis exists, you can get a top-level object from it that points to this in the global environment.

Destructuring

ES6 allows extracting values from arrays and objects and assigning values to variables in a pattern known as deconstruction

Array Destructuring

let [a, , b, ...c] = [1.2.3.4.5]
a   / / 1
b   / / 3
c   / / (4, 5)

//error
let [a] = 1  // There is no Iterator interface

let [a, b = 2, c = 3] = [1.undefined]
a / / 1.
b / / 2,
c / / 3

let [x = 1, y = x] = [];     // x=1; y=1
let [x = y, y = 1] = [];     // ReferenceError: y is not defined

// Switch positions
let x = 1, y = 2;
[y, x] = [x, y]
x / / 2
y / / 1
Copy the code

Object Destructuring

The deconstruction of an Object differs from that of an Array in one important way. The elements of an Array are arranged in order, and the value of a variable is determined by its position; The Object prop has no order. The variable must have the same name as the prop in order to get the correct value.

let { foo, baz } = { foo: 'aaa'.bar: 'bbb' };
foo // 'aaa'
baz // undefined

// Deconstruct object methods
let { log, sin, cos } = Math;
const { log } = console;
Copy the code

As stated above, destructive assignment of an object is shorthand for the following form

let { foo: baz } = { foo: 'aaa'.bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined

let obj = {
  p: [
    'Hello',
    { y: 'World'}};let { p: [x, { y }] } = obj;
p // P is not defined // P is a mode and does not participate in assignment
x // "Hello"
y // "World"
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
Copy the code

Deconstructive assignments to objects can take inherited properties.

const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);

const { foo } = obj1;
foo // "bar"
Copy the code

When the default value is set, the default value takes effect only if the property value of the object is strictly undefined.

var { message: msg = 'Something went wrong', say } = { say() { console.log(`say`)}}; msg// Something went wrong
say // function say(){}
Copy the code

Symbol

Represents a unique value. It is the seventh data type in the JavaScript language. The first six types are undefined, null, Boolean, String, Number, and Object.

let sy = Symbol('a')
let sy1 = Symbol('a')
sy === sy1  // false
sy.toString() === sy1.toString() // true
// ES2019 provides description
sy.description === sy1.description // true

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Copy the code

Both symbol.for () and Symbol() generate a new Symbol. The difference is that the former is registered for search in the global environment, while the latter is not. Instead of returning a new Symbol value on each call, symbol.for () checks to see if the given key already exists and creates a new value if it does not. For example, if you call Symbol. For (“foo”)30 times, you will return the same Symbol each time, but call Symbol(“foo”)30 times, you will return 30 different Symbol values.

Symbol.iterator

The Symbol. Iterator property of an object that points to the default iterator method for the object. This is highlighted

const myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable]  [1, 2, 3]... At the bottom is for... of
Copy the code

Object for… The Symbol. Iterator method is called, returning the default iterator for the object,

class Collection {
  *[Symbol.iterator]() {
    let i = 0;
    while(this[i] ! = =undefined) {
      yield this[i]; ++i; }}}let myCollection = new Collection();
myCollection[0] = 1;
myCollection[1] = 2;

for(let value of myCollection) {
  console.log(value);
}
/ / 1
/ / 2
Copy the code

Symbol.toStringTag

Object’s Symbol. ToStringTag property, pointing to a method. Call on the Object Object. The prototype. The toString method, if the property exists, it returns a value will appear in the toString () method returns the string, the type of the Object. That is, this property can be used to customize the string after object in [object Object] or [object Array].

({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"

class Collection {
  get [Symbol.toStringTag]() {
    return 'xxx'; }}let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"
Copy the code

Set && Map

ES6 provides new data structures Set, Map

The values of the Set members are unique, there are no duplicate values, and the elements in the Set are strongly typed and type checked.

let set = new Set([1.true.'1'.'true'.1])
// Set(4) {1, true, "1", "true"}
Copy the code

Intersect, Union, and Difference sets

let a = new Set([1.2.3]);
let b = new Set([4.3.2]);

/ / and set
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

/ / intersection
let intersect = new Set([...a].filter(x= > b.has(x)));
// set {2, 3}

// The difference set (a vs. B)
let difference = new Set([...a].filter(x= >! b.has(x)));// Set {1}
Copy the code

A Map is similar to an object in that it is a collection of key-value pairs, but the range of “keys” is not limited to strings, and all types of values (including objects) can be used as keys.

const map = new Map([['name'.'Joe'],
  ['title'.'Author']]); map.size/ / 2
map.has('name') // true
map.get('name') // "Zhang SAN"
map.has('title') // true
map.get('title') // "Author"
Copy the code

Conversion between data

Map To Array

const myMap = new Map()
  .set(true.7)
  .set({foo: 3},'abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
Copy the code

Array To Map

new Map([[true.7],
  [{foo: 3},'abc']]])// Map {
// true => 7,
// Object {foo: 3} => ['abc']
// }
Copy the code

Map To Object

function strMapToObj(strMap) {
  let obj = Object.create(null);
  for (let [k,v] of strMap) {
    obj[k] = v;
  }
  return obj;
}

const myMap = new Map()
  .set('yes'.true)
  .set('no'.false);
strMapToObj(myMap)
// { yes: true, no: false }
Copy the code

Object To Map

let obj = {"a":1."b":2};
let map = new Map(Object.entries(obj));
Copy the code

Map To JSON

function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}

let myMap = new Map().set('yes'.true).set('no'.false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
Copy the code

JSON To Map

function jsonToStrMap(jsonStr) {
  return objToStrMap(JSON.parse(jsonStr));
}

jsonToStrMap('{"yes": true, "no": false}')
// Map {'yes' => true, 'no' => false}
Copy the code

Objects referenced by WeakSet && WeakMap are weak references, that is, the garbage collection mechanism does not take this reference into account. Thus, as long as all other references to the referenced object are cleared, the garbage collection mechanism frees the memory occupied by that object. In other words, once no longer needed, the key name object and the corresponding key value pair in WeakSet && WeakMap will automatically disappear, without manual deletion of the reference.

Proxy

An overview of the

Proxy can be understood as that a layer of “interception” is set up before the target object, and the external access to the object must pass this layer of interception first. Therefore, it provides a mechanism to filter and rewrite the external access. The original meaning of the word Proxy is a Proxy, used here to mean that it “proxies” certain operations.

Object.defineproperty, on the other hand, is data hijacking in use: either define a new property on an Object directly, or modify an existing property on an Object and return the Object.

When a property of an object is accessed or modified, a piece of code intercepts this behavior, performs additional operations or modifies the returned result. The most typical application of data hijacking —–> two-way data binding (a common interview question),

  • Vue 2.xusingObject.defineProperty(), and decouple the interior toObserver.DepAnd the use ofWatcherConnected to a
  • Vue3.xAfter versionProxyimplement

ProxywithObject.definePropertyThe contrast of

  • Object.defineProperty
    • Can only listen to objects (ObjectCannot listen for array changes. Cannot triggerpush.pop.shift.unshift.splice.sort.reverse.
    • Each property of the object must be traversed
    • You can only hijack the current object properties. If you want to hijack deeply, you must deeply traverse the nested object
    "use strict"
    let obj = {};
    let value = 1
    Object.defineProperty(obj, 'listenA', {
      writable: true./ / can be modified
      enumerable: true.// Enumerable for... in... Object.keys()
      configurable: true.// Can be configured and deleted
      get: () = > value,
      set: val= > {
        console.log(`set obj.listenA .. ${val}`);
        value = val
      },
    });
    obj.listenA = 2 //set obj.listenA .. 2
    console.log(obj.listenA)  / / 2
    Copy the code
  • Proxy
    • You can listen directly to objects instead of properties
    • You can listen directly for array changes
    // Proxy the entire object
    let proxyObj = new Proxy({}, {
      get: (target, key, receiver) = > {
        console.log(`getting ${key}! `);
        return target[key];
      },
      set: (target, key, value, receiver) = > {
        console.log(target, key, value, receiver);
        returntarget[key] = value; }}); proxyObj.val =1;    // {} val 1 {}
    proxyObj.val;       // getting val!
    
    // Proxy array
    let proxyArr = new Proxy([] and {get: (target, key, receiver) = > {
        console.log(`getting ${key}! `);
        return target[key];
      },
      set: (target, key, value, receiver) = > {
        console.log(target, key, value, receiver);
        return(target[key] = value); }}); proxyArr[0] = 1; // {} val 1 {}
    console.log(proxyArr[0]); // getting val! / / 1
    console.log(proxyArr); / / [1]
    Copy the code

Reflect

Reflect translates to Reflect and, like Proxy objects, is a new API provided by ES6 for manipulating objects. There are several functions

  • willObjectObject methods that are clearly internal to the language (e.gObject.defineProperty), inReflectOn the object. At this stage, certain methods are simultaneouslyObjectandReflectObject, future new methods will only be deployed onReflectOn the object. That is to say, fromReflectObject to retrieve methods inside the language.
  • Modify someObjectMethod to make it more reasonable. For instance,Object.defineProperty(obj, name, desc)When an attribute cannot be defined, an error is thrown, andReflect.defineProperty(obj, name, desc)Will returnfalse.
 / / the old way
try {
  Object.defineProperty(target, property, attributes);
  // success
} catch (e) {
  // failure
}

/ / a new way
if (Reflect.defineProperty(target, property, attributes)) {  // Returns true on success
  // success
} else {
  // failure
}
Copy the code
  • letObjectOperations become function behavior. Some of theObjectOperations are imperative, for examplename in objanddelete obj[name]And theReflect.has(obj, name)andReflect.deleteProperty(obj, name)It turns them into functional behavior.
/ / the old way
'assign' in Object // true

/ / a new way
Reflect.has(Object.'assign') // true
Copy the code
  • ReflectObject methods andProxyObject, as long as theProxyObject methods can be used inReflectObject to find the corresponding method. This makes it easy for the Proxy object to call the correspondingReflectMethod to complete the default behavior as the basis for modifying the behavior. In other words, regardlessProxyHow to modify the default behavior that you can always do inReflectGets the default behavior on
Proxy(target, {
  set: function(target, name, value, receiver) {
    var success = Reflect.set(target, name, value, receiver);
    if (success) {
      console.log('property ' + name + ' on ' + target + ' set to ' + value);
    }
    returnsuccess; }});Copy the code

async function

The ES2017 standard makes asynchronous operations easier by introducing async functions. Since async functions return Promise objects, they can be used as arguments to await commands.

async function timeout(ms) {
  await new Promise((resolve) = > {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world'.50);
Copy the code

returnPromiseobject

async function f() {
  return 'hello world';
}

f().then(v= > console.log(v))
// "hello world"
Copy the code

Async throws an error internally, causing the returned Promise object to become reject. The thrown error object is received by the catch method callback

async function f() {
  throw new Error('Something went wrong');
}

f().then(
  v= > console.log('resolve', v),
  e= > console.log('reject', e)
)
//reject Error: Reject Error
Copy the code

PromiseThe state of the object changed

Promise objects returned by the async function will not change state until all Promise objects following the internal await command have been executed, unless a return statement is encountered or an error is thrown. That is, the callback function specified by the THEN method is executed only after the asynchronous operation within the async function has completed.

async function getTitle(url) {
  let response = await fetch(url);
  let html = await response.text();
  return html.match(/<title>([\s\S]+)<\/title>/i) [1];
}
getTitle('http://localhost:8080/').then(console.log(123))
Copy the code

awaitThe command

Normally, the await command is followed by a Promise object that returns the result of that object. If it is not a Promise object, the corresponding value is returned.

async function f() {
  / / is equivalent to
  // return 123;
  return await 123;
}

f().then(v= > console.log(v))
/ / 123
Copy the code

Any Promise object that follows an await statement becomes reject, and the entire Async function is interrupted.

async function f() {
  await Promise.reject('Something went wrong');
  await Promise.resolve('hello world'); // Will not be executed
}
Copy the code

You do not want to interrupt subsequent asynchronous operations even if the previous one fails. We can then place the first await in the try… Catch structure, so that the second await is executed regardless of whether the asynchronous operation succeeds.

async function f() {
  try {
    await Promise.reject('Something went wrong');
  } catch(e) {
  }
  return await Promise.resolve('hello world');
}

f()
.then(v= > console.log(v))
// hello world
Copy the code

asyncFunction implementation principle

Wrap the Generator function and the auto-actuator in one function

async function fn(args) {
  // ...
}

/ / is equivalent to

function fn(args) {
  return spawn(function* () {
    // ...
  });
}

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}
Copy the code

Strict mode

— ES6 modules automatically adopt strict mode, whether you use “use strict” in the module header or not;

The strict mode has the following limitations.

  • Variables must be declared before they are used
  • Function arguments must not have attributes of the same name, otherwise an error will be reported
  • You can’t usewithstatements
  • Cannot assign a value to a read-only attribute, otherwise an error is reported
  • The prefix 0 cannot be used to indicate octal, otherwise an error will be reported
  • Undeletable properties cannot be deleted, otherwise an error is reported
  • Cannot delete variablesdelete propYou can only delete the propertydelete global[prop]
  • evalNo variables are introduced in its outer scope
  • evalandargumentsCannot be reassigned
  • argumentsChanges in function parameters are not automatically reflected
  • You can’t usearguments.callee
  • You can’t usearguments.caller
  • banthisPointing to global objects
  • You can’t usefn.callerandfn.argumentsGets the stack of function calls
  • Added reserved words (e.gProtected, the staticandinterface)

export && import

Export && import is used to export and import modules.

/ / write one
export var m = 1;
/ / write two
var m = 1;
export {m};
/ / writing three
var n = 1;
export {n as m};

/ / an error
function f() {}
export f;
/ / right
export function f() {};
/ / right
function f() {}
export {f};

import 'lodash';
import 'lodash';  Lodash is loaded twice, but only executed once.

export { foo, bar } from 'my_module';  // The current module cannot use foo and bar directly
// Rename the interface
export { foo as myFoo } from 'my_module';
// Overall output
export * from 'my_module';
// Default interface
export { default } from 'foo';
export { default as es6 } from './someModule';
Copy the code

conclusion

The above is xiaobian after learning Ruan Yifeng teacher ES6 experience, I hope you correct 😜

The article recommended

  • ✍ with TypeScript, ✍ human Design patterns at the front end

  • ✍ skills like Sass will help improve development efficiency

  • ✍ interviewer will ask call, apply, and bind again. Here, here, let me give you a handwritten!

  • ✍ small white to understand | 15 minutes vue/cli complete server based rendering