preface

In this paper, the target

From the JS operation, design, data, application of four angles to comb the JS core knowledge points

Outline of topics

  1. JS run

    • Variable ascension
    • Execution context
    • scope
    • let
    • The scope chain
    • closure
    • Event loop
  2. JS design

    • The prototype
    • Prototype chain
    • this
    • call
    • apply
    • bind
    • new
    • inheritance
  3. JS data

    • The data type
    • Storage of data (shallow and deep copy)
    • Data type determination (implicit conversion, equality and congruence, equality of two objects)
    • Manipulation of data (array traversal, object traversal)
    • Calculation of data (calculation error)
  4. JS application

    • Anti-shake, throttling, curriculation

JS run

There are basically four stages

  1. Lexical analysis: The string in JS code is divided into meaningful code blocks, known as lexical units

    • When a browser first gets a JS file or script snippet, it thinks it’s a long string
    • This is incomprehensible, so break it up into meaningful code blocks such as:var a = 1
  2. Syntax analysis: Convert the lexical unit flow into an abstract syntax tree (AST), and process the generated AST tree nodes.

    • For example, using ES6 syntax, let const is converted to var.

Why do we need an abstract syntax tree?

  • Abstract syntax trees do not depend on concrete grammar, do not depend on language details, easy to do a lot of operations
  • On the other hand, there are many languages, C, C++, Java, Javascript, etc., that have different language specifications
  • However, when converted into an abstract syntax tree, they are all consistent, which makes it easier for the compiler to add, delete, modify, and check them.
  1. Pre-parsing phase:

    • The scope rules are determined
    • Variables and functions are promoted
  2. Execution stage:

    • Create the execution context and generate the execution context stack
    • Execute executable code according to the event loop

1. Scope

Specifies the scope of functions and variables

  • Divided intoGlobal scopeandFunction scope.
  • Unlike C and JAVA, JS has no block-level scope, which is simply the scope of curly braces

2. Variables and functions are promoted

Global variable and function declarations are improved

  • There are three ways to declare functions,
    • function foo() {}
    • var foo = function () {}
    • var foo = new Function()
    • They fall into two categories,Directly to createandVariable assignment
  • Variable assignment functionandAssign a normal variableIs overridden by the same variable name
  • Function creation takes precedence over variable assignment, regardless of position. In other words, function creation takes precedence even after variable declaration

3. Execution context

With different scopes, there are different execution environments, and we need to manage the variables of those contexts

  • There are three types of execution environments. The execution context corresponds to the execution environment
    • Global execution environment
    • Function execution environment
    • Eval Execution environment (performance issues aside)
  1. Global execution context
    • So let’s look at the variable declaration,
    • Let’s look at the function declaration
  2. Function execution context
    • Look for function parameters and variable declarations
    • Assign an argument to a parameter
    • Find a function declaration
  • Multiple nested functions give you multiple execution contexts, which requiresExecution context stackTo maintain, last in, first out
  • The execution context containsThe variable environmentandLexical environment
  • The variable environmentContains variables that can be used in the current environment
  • The current environment is useless. That’s itThe scope chain

4. Scope chain

  • Reference to the definition of JS elevation: scope chain to ensure orderly access to variables and functions that the execution environment has access to
  • Variables are looked up not in the order of the execution context stack, but byLexical scopeDecision of the
  • The lexical scope is justStatic scopeIt depends on where the function is declared, and it doesn’t matter where the function is called

5. Static and dynamic scopes

  • Lexical scope is determined when writing code or definitions
  • Dynamic scope is determined at run time (This too!)
    var a = 2;
    function foo() {
        console.log(a); // Static 2 dynamic 3
    }
    function bar() {
        var a = 3;
        foo();
    }
    bar();
Copy the code

closure

  • Due to thescopeWe can’t access variables defined inside a function from outside the scope of the function, which is what we use hereclosure
  • A closure is a function that has access to a variable in the scope of another function

1. Closures

  • The for loop iterates through for event bindingThe output I value is the length of the for loop +1
  • This result is not what we want, because JS has no block-level scope, var defines the I value, and is not destroyed, stored in the global variable environment
  • The value of I taken at the time the event is executed is the value of I computed multiple times in the global variable
    for(var i = 0; i <3; i++){document.getElementById(`item${i+1}`).onclick = function() {
            console.log(i);// 3,3,3}}Copy the code
  • Closure features: The external function has finished executing, the internal function reference external function variables are still stored in memory, the set of variables can be calledclosure
  • During the compilation process, the JS engine will do a method scan for internal functions. If the variables of external functions are referenced, the heap space will be createdClosureObject to store closure variables
  • Use this feature to add a closure to the method to store the current I value and bind the event to the function returned by the new anonymous function
for(var i = 0; i <3; i++){document.getElementById(`item${i+1}`).onclick = make(i);
}
function make(e) {
    return function() {
        console.log(e)//0,1,2
};
Copy the code

Closure notice

  • We’ve inadvertently written closures where the variables that the inner function refers to the outer function are still stored in memory,
  • What should be destroyed is not destroyed,Failure of a program to free memory that is no longer in use due to negligence or errorIs caused byA memory leak
  • Also note that closures do not cause memory leaks; they do when we use them incorrectly

Event loop

  • JS code executes according to an event loop
  • JS is single-threaded and ensures execution is not blocked by asynchrony
  1. Enforcement mechanism
    • Basically, one execution stack, two task queues
    • If you find a macro task, you put it in the macro task queue, if you find a microtask, you put it in the microtask queue,
    • When the execution stack is empty, all the micro tasks in the micro task queue are executed, and then one macro task in the macro task queue is executed
    • The cycle
  2. MacroTask: setTimeout, setInterval, I/O, UI rendering microTask: Promise.then

Ii. JS design

1. The prototype

  1. The design of JS
  • There are new operators and constructors, but there is no concept of a class. Instead, we use prototypes to simulate classes to implement inheritance
  1. JS design heart process
  • JS was designed to be a simple web scripting language with a short time frame, not too complex, and intended to mimic Java concepts (that’s why it’s called JavaScript).
  • So we borrowed from Javaobject,The constructor,newThe idea of the operator, while abandoning the complexclass(Class) concept
  1. Inheritance mechanism
  • There needs to be oneinheritanceTo link all objects together, you can use constructors
  • But the downside of constructors generating instance objects is thatUnable to share properties and methods
  1. prototypeattribute
  • In order to solve the above problem, we introduceprototypeAttributes are what we call archetypes
  • Set one for the constructorprototypeProperties, methods that instance objects need to share, all put on this object,

Once the entire core design is complete, the following apis are in order

The prototype

  • Each JS object is associated with another object when it is created
  • This object is the stereotype, and every object inherits properties from the stereotype

proto

  • Every object has a property called __proto__, which points to the object’s prototype
  • The prototype property of the constructor is equal to the __proto__ property of the instantiated object
  • This property is not a standard property in ES5, but is just a syntactic sugar to make it easy to get the prototype in the browser,
  • We can useObject.getPrototype()Method to obtain prototype

The constructor stereotype does not point to an instance, because a constructor can have multiple object instances, but there are prototype-pointing constructors, and each stereotype has a constructor attribute pointing to the associated constructor

function Per() {} // constructor
const chi = new Per() // Instance object

chi.__proto__ ===  Per.prototype // Get the prototype of the object as the constructor's Prototype property
Per.prototype.constructor === Per The constructor property gets the constructor for the current stereotype association

Copy the code

Examples and prototypes

  • When reading instance properties and not finding them, it looks for the properties of the prototype associated with the object, all the way up,
  • This chain between the instance and the prototype is formedPrototype chain
    function Foo() {}
    Foo.prototype.name = 'tom'
    const foo = new Foo()
    foo.name = 'Jerry'
    console.log(foo.name); // Jerry
    delete foo.name
    console.log(foo.name); // tom
Copy the code

2. The prototype chain

Let’s start with the familiar web map

This is the chain between the instance and the constructor, the prototype

  • The proTO of the instance points to the prototype

  • The prototype property of the constructor points to the prototype

  • The stereotype’s constructor property points to the constructor

  • All constructor proTos point to function.prototype

  • Prototype Proto points to Object. Prototype

  • Prototype Proto points to null

Prototype is a machine that builds constructor functions (Object, String, Number, Boolean, Array, Function). The constructor then creates the concrete instance object

function Foo() {}
// 1. All constructors' __proto__ points to function.prototype
Foo.__proto__ ƒ () {[native code]}
Function.__proto__ ƒ () {[native code]}
Object.__proto__ ƒ () {[native code]}

// 2. All constructor prototypes and new Object instances created by __proto__ point to Object.prototype
var o = new Object()
o.__proto__ / / {constructor: ƒ, __defineGetter__ : ƒ, __defineSetter__ : ƒ... }
Function.prototype.__proto__  / / {constructor: ƒ, __defineGetter__ : ƒ, __defineSetter__ : ƒ... }

// 3. object. prototype points to null
Object.prototype.__proto__ // null

Copy the code

2. this

  1. When called as an object method, points to that objectobj.b();/ / points to obj `
  2. Called as a function method,var b = obj.b; b();// point to the global window.
  3. Called as a constructorvar b = new Per();// This points to the current instance object
  4. Called as call with applyobj.b.apply(object, []);// This points to the currently specified value

It points to whoever calls it


const obj = {a: 1.f: function() {console.log(this.this.a)}}
obj.f(); / / 1

const a = 2;
const win = obj.f;
win(); / / 2

function Person() {
    this.a = 3;
    this.f = obj.f;
}
const per = new Person()
per.f() / / 3

const app = { a: 4 }
obj.f.apply(app); / / 4
Copy the code

This point is dynamically scoped, who calls to whom,

3. call

  1. Definition: Calls a function or method with a specified this value and several specified parameter values
  2. For example:
var obj = {
    value: 1,}function foo (name, old) {
    return {
        value:this.value, 
        name, 
        old
    }
} 
foo.call(obj, 'tom'.12); // {value: 1, name: "tom", old: 12}
Copy the code
  1. Requirements:
  • Call changes the direction of this,
  • The foo function is executed
  • Supports parameter transmission and the number of parameters is not fixed
  • The this argument can be passed to null, which points to the window
  • A function can have a return value
  • Non-function call judgment processing
  1. Implementation and Ideas
Function.prototype.call1 = function (context, ... args) {
    if(typeof this! = ='function') {throw new Error('Error')} // Non-function call judgment processing
    context = context || window; // The non-operator determines that the passed argument null points to the window
    const key = Symbol(a);// Use symbol to create a unique attribute name to prevent overwriting the original attribute
    context[key] = this; // If the function is an object attribute, the function's this refers to the object
    constresult = context[key](... args)// Temporary variables are assigned to execute object methods
    delete context[key]; // Delete methods to prevent contaminating objects
    return result // return temporary variable
}
Copy the code
  1. Application scenarios

Change the this pointer, mostly to borrow methods or attributes

    1. Determine the data type and borrowObjectthetoStringmethodsObject.prorotype.toString.call()
    1. Subclasses inherit superclass attributes,function Chi() {Par.call(this)}

4. apply

  1. Definition: Calls a function or method with a specified this value and an array containing specified parameter values
  2. For example:
var obj = {
    value: 1,}function foo (name, old) {
    return {
        value:this.value, 
        name, 
        old
    }
} 
foo.apply(obj, ['tom'.12].24); // {value: 1, name: "tom", old: 12}
Copy the code
  1. Requirements:
  • Call changes the direction of this,
  • The foo function is executed
  • The second parameter is an array. The following parameters are invalid. The number of parameters in the array is not fixed.
  • The this argument can be passed to null, which points to the window
  • A function can have a return value
  • Non-function call judgment processing
  1. Implementation and Ideas
Function.prototype.apply1 = function (context, args) { // The only difference from the call implementation is that it is not destructed here
    if(typeof this! = ='function') {throw new Error('Error')} // Non-function call judgment processing
    context = context || window; // The non-operator determines that the passed argument null points to the window
    const key = Symbol(a);// Use symbol to create a unique attribute name to prevent overwriting the original attribute
    context[key] = this; // If the function is an object attribute, the function's this refers to the object
    constresult = context[key](... args)// Temporary variables are assigned to execute object methods
    delete context[key]; // Delete methods to prevent contaminating objects
    return result // return temporary variable
}
Copy the code
  1. Application scenarios
  • With the call

5. bind

  1. define
    • The bind method creates a new function
    • When the new function is called, the first argument is runtime this,
    • The subsequent argument is passed as its argument before the argument is passed
  2. For example,
const obj = {
    value: 1
};
function foo(name, old) {
    return {
        value: this.value,
        name,
        old
    }
}
const bindFoo = foo.bind(obj, 'tom'); 
bindFoo(12); // {value: 1, name: "tom", old: 12}
Copy the code
  1. requirements
    • Returns a function whose first argument is this when executed
    • You can pass some parameters when you bind and some parameters when you execute a function
    • Bind as a constructor, this is invalid, but the argument is valid,
    • And when used as a constructor, the stereotype points to the stereotype of the binding function so that the instance inherits the values in the stereotype
    • Non-function calls bind judgment processing
  2. Implementation and Ideas
Function.prototype.bind1 = function (context, ... args) {
    if(typeof this! = ='function') {throw new Error('Error')} // Non-function call judgment processing
    const self = this; // Save this for the current execution environment
    const Foo = function() {} // Save the original function prototype
    const res = function (. args2) { // Create a function and return it
        return self.call( // return within the function
            this instanceof res ? this : context, // As a constructor, this points to the instance, and as a normal function this normally points to the passed context
             ...args, ...args2) // Both passed arguments are returned as arguments
    }
    Foo.prototype = this.prototype; // Use empty function transitions to ensure that the bind prototype is not polluted when new function prototypes change
    res.prorotype = new Foo();
    return res;
}
Copy the code

6. new

Let’s see what the new instance can do. Okay

  • The properties of the constructor are accessible
  • Access prototype’s properties
  • If the constructor returns a value, it returns an object. The instance can access only the properties of the returned object. This is not valid
  • Return the value of the primitive type. This is valid
function Persion(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function () {
    console.log(this.name)
}
var per = new Person('tom'.10)
per.name // 10 Can access constructor properties
per.sayName // Tom accesses prototype's properties
Copy the code

The new implementation

var person = factory(Foo)

function factory() { // New is a keyword that cannot be overridden
    var obj = {}; // Create object obj
    var con = [].shift.call(arguments); // Get the constructor
    obj._proto_ = con.prototype; // the obj prototype points to the constructor prototype
    var res = con.apply(obj, arguments); // The constructor this points to obj
    return typeof(res) === 'object' ? ret : obj;
}
Copy the code

7. Inheritance

  1. Prototype chain inheritance and prototype inheritance
  • You cannot pass parameters to the parent class. You can only share attributes
  1. Borrow constructors and parasitic inheritance
  • Methods are not in the prototype and must be recreated each time
  1. Combination of inheritance
  • Although the above two problems were solved, the father was called twice,
  • The same properties are used for instance and prototype
  1. Parasitic combinatorial inheritance
  • The current best plan

Parasitic composite inheritance implementation

function P (name) { this.name = name; } // Dynamically pass parameters to bind attributes on the parent class
P.prototype.sayName = function() { // Bind methods on the superclass prototype
    console.log(111)}function F(name) { // The subclass function uses the 'call' function this to point to the subclass, pass the argument, and execute
    P.call(this, name)
}
const p = Object.create(P.prototype) // object.create does not inherit redundant properties and methods from constructors
p.constructor = F; // The constructor attribute is lost and redirected
F.prototype = p; // The subclass prototype points to the transit object

const c = new F('tom'); // Instantiate the subclass
c.name // tom
c.sayName() / / 111
Copy the code

JS data

1. Data types

JS is divided into basic types and reference types

  • Basic types:Boolean Undefined String Number Null Symbol
  • Reference type:Object Funciton Array

2. Data storage (shallow copy)

Js data types are divided into basic types, and reference types

  1. Base types are stored in stack memory
  • When you assign, the compilation system creates a new block of memory to store the new variable so the primitives are disconnected when they are assigned
  1. Reference types are kept in heap memory
  • Assignment is just a copy of the address of the object without creating a new memory, a copy of the address of the heap, both pointing to the same address
  • Modify one and the other will be affected

Two objects point to the same address and changing one affects the other

Special array object method (deep copy layer)

  1. obj2 = Object.assign({}, obj1)

  2. arr2 = [].concat(arr1)

  3. arr2 = arr1.slice(0)

  4. arr2 = Array.form(arr1)

  5. arr2 = […arr1];

All the above methods can only copy one layer deep

Parse (json.stringify (obj)) (multilayer) Instead of copying an object, copying a string opens up a new memory address and breaks the pointer connection to the reference object

disadvantages

  1. Time object => as a string
  2. RegExp, Error => returns empty objects
  3. The function, undefined = > lost
  4. NaN, Infinity, and -infinity => serialize to NULL
  5. Objects are generated by constructors => which discard the object constructor
  6. Deep copy is also impossible with circular references

Implementing deep copy manually (multiple layers)

    function Judgetype(e) {
        return Object.prototype.toString.call(e).slice(8, -1).toLowerCase();
    }
    function Loop(param) {
        let target = null;
        if(Judgetype(param) === 'array') {
            target = [];
            for(let key ofparam.keys()){ target[key] = Deep(param[key]); }}else {
            target = {};
            Object.keys(obj).forEach((val) = >{ target[key] = Deep(param[key]); })}return target;
    }
    function Deep(param) {
        // Basic data type
        if(param === null| | -typeofparam ! = ='object' && typeofparam ! = ='function')) {
            return param;
        }
        / / function
        if(typeof param === 'function') {   
            return new Function('return ' + param.toString())();
        }
        return Loop(param);
    }
Copy the code

3. Data type judgment (type judgment, equality and congruence, implicit conversion, equality of two objects)

  1. Type judgment

typeof

  • Object, NULL, and array cannot be distinguished
  • For primitive types, all but NULL returns the correct result.
  • For reference types, return object all but function
typeof(1) // number
typeof('tom') // string
typeof(undefined) // undefined
typeof(null) // object
typeof(true) // boolean
typeof(Symbol(1)) // symbol

typeof({a: 1}) // object
typeof(function () {}) // function
typeof([]) // object
Copy the code

instanceof

  • Determines whether an instance belongs to a type
[] instanceof Array; // true
{} instanceof Object;// true

var a  = function (){}
a instanceof Function // true


Copy the code

Object.prototype.toString.call

  • The current best plan

  • ToString () is a prototype method for Object that, by default, returns the current Object’s [[Class]]. This is an internal property of the form [object Xxx], where Xxx is the type of the object.

  • For Object objects, toString() returns [Object Object]. For other objects, you need call/apply to return the correct type information

  • Here is the application scenario of Call, clever use of call borrow Object method to achieve type judgment

function T(e) {
    return Object.prototype.toString.call(e).slice(8, -1).toLowerCase();
}
T(1) // number
T('a') // string
T(null) // null
T(undefined) // undefined
T(true) // boolean
T(Symbol(1)) // symbol

T({a: 1}) // object
T(function() {}) // function
T([]) // array
T(new Date()) // date
T(/at/) // RegExp
Copy the code
  1. Equality and congruence
  • = =Non-strict comparisons allow type conversions
  • = = =Strict comparisons do not allow type conversions

The reference data type stack holds the address, and the heap holds the content, even though the content is the same, but the address is different, so the two are not equal

const a = {c: 1}
const b = {c: 1}
a === b // false
Copy the code
  1. Implicit conversion
  • = =There may be type conversions, not only for equality comparisons, but also for operations, and that’s what we call implicit conversions

Boolean comparison, number first

true= =2 // false
||
1= =2
// if(X)
var X = 10
if(X) // true
10= = >true

// if(X == true)
if(X == true) // false
10= =true
|| 
10= =1
Copy the code

Comparing numbers to strings,stringturndigital

0= =' ' // true
||
0= =0

1= ='1' // true
||
1= =1


Copy the code

An equality comparison between an object type and a primitive type


[2] = =2 // true
|| valueOf() // Call valueOf() to get its own value
[2] = =2
|| toString() // Call toString() to convert the string
"2"= =2
|| Number(a)// // To compare numbers with strings, 'string' goes to 'number'
2= =2

Copy the code

summary

Js uses certain operators that result in type conversions, typically +, ==

  1. When the operation
  • The addition of a string exists by converting it to a string
  • Multiply – divide – subtraction all strings go to numbers
  1. Equal comparison
  • Boolean comparison, number first
  • Comparing numbers to strings,stringturndigital
  • The object type is changed to the original type first

A == 1&&a == 2&&a == 3

const a = {
  i: 1.toString: function () {
    return a.i++;
  }
}
a == 1 && a == 2 && a == 3
Copy the code
  1. Determines the value of two objects to be equal
  • The reference data type stack holds the address, the heap holds the content, even though the content is the same, but the address is different, so= = =The two are not equal
  • But how do we know they’re equal if they’re quoting the same data?
// Check that both objects are not returned
// Check whether the length is consistent
// Check whether the key values are the same
// Check whether the corresponding key values are the sameWe're just thinking about objects that have values like object, array, number,undefined.null, String, Boolean About some special types`function date RegExp`Don't take afunction Judgetype(e) {
    return Object.prototype.toString.call(e).slice(8, -1).toLowerCase();
}
function Diff(s1, s2) {
    const j1 = Judgetype(s1);
    const j2 = Judgetype(s2);
    if(j1 ! == j2){return false;
    }
    if(j1 === 'object') {
        if(Object.keys(s1).length ! = =Object.keys(s2).length){
            return false;
        }
        s1[Symbol.iterator] = function* (){
            let keys = Object.keys( this )
            for(let i = 0, l = keys.length; i < l; i++){
                yield {
                    key: keys[i],
                    value: this[keys[i]] }; }}for(let {key, value} of s1){
            if(! Diff(s1[key], s2[key])) {return false}}return true
    } else if(j1 === 'array') {
        if(s1.length ! == s2.length) {return false
        }
        for(let key of s1.keys()){
            if(! Diff(s1[key], s2[key])) {return false}}return true
    } else return s1 === s2
}

Diff( {a: 1.b: 2}, {a: 1.b: 3}) // false
Diff( {a: 1.b: [1.2] {},a: 1.b: [1.3]}) // false
Copy the code

Object traversal return can also be used for in. The side effects of traversal prototype can be compensated with hasOwnproperty judgment

  • Object for of traversal also have to add their own iterator, more troublesome
    for(var key in s1) {
        if(! s1.hasOwnProperty(key)) {if(! Diff(s1[key], s2[key])) {return false}}}Copy the code

4. Data manipulation (array traversal, object traversal)

1. Array traversal

'Most common for loop' // It's a hassle
for(let i = 0,len = arr.length; i < len; i++) {
    console.log(i, arr[i]);
}

`forEach`Can'tbreak return

`for in`Not suitable for traversing groups of numbers,`for... in`The statement is defined at the W3C to iterate over a group of attributes or objects1.Index The index is a string number and cannot be directly used for geometric operations2.The traversal order may not be in the internal order of the actual array3.usefor inAll enumerable properties of the array are iterated through, including stereotypes`for of`Unable to get subscript// for for 1
for(let [index,elem] of new Map( arr.map( ( item, i ) = >[ i, item ] ) )){console.log(index);console.log(elem);
}

// for for 2
let arr = [1.2.3.4.5];
for(let key of arr.keys()){
    console.log(key, arr[key]);
}
for(let val of arr.values()){
    console.log(val);
}
for(let [key, val] of arr.entries()){
    console.log(key, val);
}

2. 
Copy the code

2. Object traversal

  1. for in

Cons: Iterates through all enumerable properties of an object, such as those on Prototype

var obj = {a:1.b: 2}
obj.__proto__.c = 3;
Object.prototype.d = 4
for(let val in obj) {
    console.log(val) // a,b,c,d
}
/ / optimization
for(let val in obj) {
    if(obj.hasOwnProperty(val)) { // The judgment attribute exists in the current object instance itself, not in the prototype
        console.log(val) // a,b}}Copy the code
  1. object.keys
var obj = { a:1.b: 2 }
Object.keys(obj).forEach((val) = > {
    console.log(val, obj[val]); 
    // a 1
    // b 2
})
Copy the code
  1. for of
  • Only data types that provide an Iterator interface can use for-of
  • Types such as Array are provided by default
  • We can add a Symbol. Iterator property to the object
var obj = { a:1.b: 2 }
obj[Symbol.iterator] = function* (){
    let keys = Object.keys( this )
    for(let i = 0, l = keys.length; i < l; i++){
        yield {
            key: keys[i],
            value: this[keys[i]] }; }}for(let {key, value} of obj){
    console.log( key, value );
    // a 1
    // b 2
}
Copy the code

5. Data calculation (calculation error)

  1. 0.1 + 0.2 = 0.30000000000000004
  • All the numbers will be converted to binary, calculated bit by bit,
  • Decimal binary not bisected will loop indefinitely
  • Js data store 64-bit double precision floating point numbers, not to be described here, exceeding will be truncated (large number calculation error and limitation also because of this)
  • When you add them up and convert them back, you get an error
  1. So how do you make an accurate calculation
  • For the numeric decimal itself does not exceed the JS storage number of decimal, can be changed to an integer at the same time, after calculation to decimal again
function getLen(n) {
    const str = n + ' ';
    const s1 = str.indexOf('. ')
    if(s1) {
        return str.length - s1 - 1
    } else {
        return 0}}function add(n1, n2) {
    const s1 = getLen(n1)
    const s2 = getLen(n2)
    const max = Math.max(s1, s2)
    return (n1 * Math.pow(10, max) + n2 * Math.pow(10, max)) / Math.pow(10, max)
}
add(11.2.2.11) / / 13.31
Copy the code
  • For more than the number of digits can be converted to an array, the reverse order of the sum of bits, more than 10 carry, string concatenation to get the value
function add(a, b) {
    let i = a.length - 1;
    let j = b.length - 1;
    let carry = 0;
    let ret = ' ';
    while(i>=0|| j>=0) {
        let x = 0;
        let y = 0;
        let sum;
        if(i >= 0) {
            x = a[i] - '0';
            i--
        }
        if(j >=0) {
            y = b[j] - '0';
            j--;
        }
        sum = x + y + carry;
        if(sum >= 10) {
            carry = 1;
            sum -= 10;
        } else {
            carry = 0
        }
        ret = sum + ret;
    }
    if(carry) {
        ret = carry + ret;
    }
    return ret;
}
add('999999999999999999999999999999999999999999999999999999999999999'.'1') 
//  1000000000000000000000000000000000000000000000000000000000000000
Copy the code

4. JS application

1. If you

Scene:

  • Search box input pull down association, request background interface, in order to avoid frequent requests, to the server caused pressure

Definition:

  • If an event is triggered within n seconds of the event being triggered, the new event will prevail

Realization idea:

  1. Timer execution and clearing
  2. Apply changes the this pointer
  3. Apply pass parameter inheritance
function debounce(func, wait) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        clearTimeout(timeout)
        timeout = setTimeout(function(){ func.apply(context, args) }, wait); }}Copy the code

2. The throttle

Scene:

  • Some events can be triggered less frequently.
  • For example, the position of the scroll bar should be monitored during lazy loading, but it does not need to be triggered every time it slides, which can reduce the frequency of calculation without wasting resources.

Definition:

  • Events are continuously triggered and executed only once within a specified period of time
  1. Method 1: Timestamp
  • Realization idea:
    • Trigger time takes the current timestamp now, minus the flag timestamp (initial value is 0)
    • If the time is longer than the specified time, the command is executed and the flag is updated to the current time.
    • If the time is shorter than the specified time, the system does not execute the command
function foo(func, wait) {
    var context, args;
    var flag = 0;
    return function () {
        var now = +new Date(a); context =this;
        args = arguments;
        if(now - flag > 0) { func.apply(context, args); flag = now; }}}Copy the code
  1. Method two: timer
  • Realization idea:
    • Check whether there is a timer.
    • Do not define the timer, to the specified time to execute, and empty the timer
    • If so, it will not be executed
function foo(func, wait) {
    var context, args;
    var timeout;
    return function() {
        if(! timeout){setTimeout(() = >{
                timeout = null;
                func.apply(context, args);
            }, wait) 
        }
    }
}
Copy the code

3. Mr Currie

  1. Definition: Converts a function that takes multiple arguments to a function that takes a single argument, and returns a new function that takes the remaining arguments and returns the result
  2. Features:Parameters of reuse.Return early.Delay the
  3. The implementation process
  • Create a function that uses Apply to re-pass the merged arguments to the Currified function
  • Construct a final return value by iterating through all the items in the reduce array
function add(. args) {
	var fn = function(. args1) {
        return add.apply(this, [...args, ...args1]);
    }
    fn.toString = function() {
        return args.reduce(function(a, b) {
            returna + b; })}return fn;
}
add(1) (2) (3).toString(); / / 6

Copy the code