This is the sixth day of my participation in the August Text Challenge.More challenges in August

Let and const

Temporary dead zone

Typeof is no longer safe because of let. Previously, using Typeof for variables declared unassigned would result in undefined, but using let would result in a closed scope, and a reference error would be reported if typeof was used for variables declared unassigned

Benefits (es6 lets and const instead of var in ES5)

You can avoid the following two types of errors

  1. Variables are used before declaration
  2. Declare the same variable in the same scope

Why do you need block-level scopes

  1. Since variables declared using var have variable promotion (variables can be used before the declaration and have a value of undefined), function-scoped variables can override globally-scoped variables
  2. Count variables declared in the body of the loop are leaked as global variables after the loop ends

Es6 is the birth of block-level scopes

The closed scope created using lets is equivalent to adding block-level scope

Block-level scope scope

Can replace immediate function expression (IIFE)

Characteristics of const

  1. Once declared, the value cannot be changed (essentially to ensure that the memory address the variable points to remains the same)
  2. For simple data types, the value is stored at the memory address the variable points to (on the stack)
  3. For reference data types, a variable holds a pointer to a memory address (in the heap), and const is guaranteed to keep the memory address unchanged, but the data it holds is mutable
  4. Because of the first point, it must be initialized at declaration time, otherwise an error will be reported

Const stores reference variable examples

const foo = {};

// Add an attribute to foo
foo.prop = 123;
foo.prop / / 123
Copy the code
const a = [];
a.push('Hello'); / / the executable
a.length = 0;    / / the executable
Copy the code

Declare a frozen object using const

Frozen object

const foo = Object.freeze({});

// In normal mode, the following line does not work;
// In strict mode, this line will report an error
foo.prop = 123;
Copy the code

Freezing objects and their object properties (recursive freezing)

var constantize = (obj) = > {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) = > {
    if ( typeof obj[key] === 'object') { constantize( obj[key] ); }}); };Copy the code

ES6 variable declaration

  • Var (formerly ES5)
  • Function (formerly ES5)
  • let
  • const
  • import
  • class

Properties of the top-level object

Properties of top-level objects in ES5 are equivalent to global variables

The disadvantages are as follows:

  1. Undeclared errors cannot be reported at compile time and can only be detected at run time (because global variables can be created by attributes of top-level objects, and attribute creation is dynamic)
  2. The global variables generated by the misoperation result in the properties of the top-level object can be exported and read, which is not conducive to the implementation of modular programming

Variables declared using the new four methods in ES6 do not become attributes of top-level objects

var a = 1;
// If in the REPL environment of Node, it can be written as global.a
// Or, in general, write this.a
window.a / / 1

let b = 1;
window.b // undefined
Copy the code

Take the top-level object from any environment

/ / method
(typeof window! = ='undefined'
   ? window
   : (typeof process === 'object' &&
      typeof require= = ='function' &&
      typeof global= = ='object')?global
     : this);

/ / method 2
var getGlobal = function () {
  if (typeofself ! = ='undefined') { return self; }
  if (typeof window! = ='undefined') { return window; }
  if (typeof global! = ='undefined') { return global; }
  throw new Error('unable to locate global object');
};
Copy the code

Symbol

The characteristics of

Is the seventh data type of ES

A reason for

The attributes of objects are all strings, which is easy to cause attribute name conflicts. Symbol can ensure that the attribute names of objects are unique

Declare the Symbol variable

  • Instead of calling the Symbol function with new, call it directly — see Example 1
  • You can pass in parameters when calling Symbol to customize the identity — see Example 2
  • When we call Symbol with an object, the object’s toString method is called and a Symbol value is generated — see Example 3
  • Symbol is a new special data type that cannot be evaluated with other data types — see Example 4
  • Although it cannot be evaluated with other data type variables, it can be shown converted to a string or Boolean, but not to a numeric value — see Example 5

Case 1

let symb = Symbol(a)Copy the code

Case 2

let s1 = Symbol('s1')
let s2 = Symbol('s2')

s1
Symbol(s1)
s1.toString()
"Symbol(s1)"

s2
Symbol(s2)
s2.toString()
"Symbol(s2)"

let s3 = Symbol('s1')
s3
Symbol(s1)
s1 == s2
false
s1 == s3
false
Copy the code

Example 3

const obj3 = {
	toString() {
		return 'abc'}}const sym3 = Symbol(obj3)
console.log(sym3)
Symbol(abc)

const obj4 = {
	name: 'obj4'
}
const sym4 = Symbol(obj4)
console.log(sym4)
Symbol([object Object])
Copy the code

Example 4

const str5 = 'I am a string';
const sym5 = Symbol('sym5')
const result5 = str5 + sym5;
console.log(result5);

Uncaught TypeError: Cannot convert a Symbol value to a string
Copy the code

Class (class)

nature

  • Object template
  • Equivalent to syntactic sugar (most functions can be done on ES5)

Interpretation of the

  • Constructs in ES5functionCorresponds to constructs in ES6methods
  • The essence of a class is still a function — see Example 1
  • The class itself points to the constructor — see example 1
  • All methods of a class are defined in the classprototypeProperty above (so can be passed inprototypeAdding a method to an object adds a new method to a class) — see Examples 2, 3
  • Methods defined inside classes are not enumerable (but inside functions in ES5)defineIs enumerable) — see examples 4 and 5
  • Classes must be called using the new keyword, unlike ES5 functions (which can be executed directly).
  • Properties of ES5&ES6 instances are defined on stereotypes (classes) unless they are explicitly defined on themselves (defined on this object) — see Example 6
  • All instances of ES5&ES6 share the same stereotype object
  • The prototype object (proto) (protoEnvironment dependent, used in productionObject.getPrototypeOfMethods can be added to a class (but are not recommended, and will change the original definition of the class, affecting all instances).

Case 1

class Point {
  // ...
}

typeof Point // "function"
Point === Point.prototype.constructor // true
Copy the code

Case 2

class Point {
  constructor() {
    // ...
  }

  toString() {
    // ...
  }

  toValue() {
    // ...}}/ / is equivalent to

Point.prototype = {
  constructor() {},
  toString() {},
  toValue(){}};Copy the code

Example 3

class Point {
  constructor(){
    // ...}}Object.assign(Point.prototype, {
  toString(){},
  toValue(){}});Copy the code

Example 4

class Point {
  constructor(x, y) {
    // ...
  }

  toString() {
    // ...}}Object.keys(Point.prototype)
/ / []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
Copy the code

Case 5

var Point = function (x, y) {
  // ...
};

Point.prototype.toString = function() {
  // ...
};

Object.keys(Point.prototype)
// ["toString"]
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
Copy the code

Case 6

/ / define the class
class Point {

  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ') '; }}var point = new Point(2.3);

point.toString() / / (2, 3)

point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
Copy the code

Store values and values

  • The property setting store/value function intercepts the value of the property using the get/set keywordAccess behavior– see case 1
  • ES5&ES6 Store and value functions are description objects set in propertiesDescriptor— see Example 2

Case 1

class MyClass {
  constructor() {
    // ...
  }
  get prop() {
    return 'getter';
  }
  set prop(value) {
    console.log('setter: '+value); }}let inst = new MyClass();

inst.prop = 123;
// setter: 123

inst.prop
// 'getter'
Copy the code

Case 2

class CustomHTMLElement {
  constructor(element) {
    this.element = element;
  }

  get html() {
    return this.element.innerHTML;
  }

  set html(value) {
    this.element.innerHTML = value; }}var descriptor = Object.getOwnPropertyDescriptor(
  CustomHTMLElement.prototype, "html"
);

"get" in descriptor  // true
"set" in descriptor  // true
Copy the code

Deconstruction assignment

Deconstruction conditions

A data structure with an Iterator interface

counter-examples

/ / an error
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
Copy the code

Special case

function* fibs() {
  let a = 0;
  let b = 1;
  while (true) {
    yielda; [a, b] = [b, a + b]; }}let [first, second, third, fourth, fifth, sixth] = fibs();
sixth / / 5
Copy the code

Reason: Generator functions have an Iterator interface natively

Deconstruct the assignment to default values

let [x, y = 'b'] = ['a'.undefined]; // x='a', y='b'
Copy the code

The default value is not satisfiedStrictly equal to (i.e. ===)Is triggered in the case of

let [x = 1] = [null];
x // null
Copy the code

The default value is that the expression is lazily evaluated, i.e

function f() {
  console.log('aaa');
}

let [x = f()] = [1];
Copy the code

Is equivalent to

let x;
if ([1] [0= = =undefined) {
  x = f();
} else {
  x = [1] [0];
}
Copy the code

The deconstructive assignment of an object can take inherited properties

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

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

The prototype object of obj1 is obj2. The foo property is not a property of obj1 itself, but a property inherited from obj2 that can be retrieved by deconstruction assignment