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
-
JS run
- Variable ascension
- Execution context
- scope
- let
- The scope chain
- closure
- Event loop
-
JS design
- The prototype
- Prototype chain
- this
- call
- apply
- bind
- new
- inheritance
-
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)
-
JS application
- Anti-shake, throttling, curriculation
JS run
There are basically four stages
-
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
-
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.
-
Pre-parsing phase:
- The scope rules are determined
- Variables and functions are promoted
-
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 into
Global scope
andFunction 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 create
andVariable assignment
Variable assignment function
andAssign a normal variable
Is 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)
- Global execution context
- So let’s look at the variable declaration,
- Let’s look at the function declaration
- 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 requires
Execution context stack
To maintain, last in, first out - The execution context contains
The variable environment
andLexical environment
The variable environment
Contains variables that can be used in the current environment- The current environment is useless. That’s it
The 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 by
Lexical scope
Decision of the - The lexical scope is just
Static scope
It 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 the
scope
We 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 binding
The 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 called
closure
- 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 created
Closure
Object 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 error
Is 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
- 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
- MacroTask: setTimeout, setInterval, I/O, UI rendering microTask: Promise.then
Ii. JS design
1. The prototype
- 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
- 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 Java
object
,The constructor
,new
The idea of the operator, while abandoning the complexclass
(Class) concept
- Inheritance mechanism
- There needs to be one
inheritance
To link all objects together, you can use constructors - But the downside of constructors generating instance objects is that
Unable to share properties and methods
prototype
attribute
- In order to solve the above problem, we introduce
prototype
Attributes are what we call archetypes - Set one for the constructor
prototype
Properties, 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 use
Object.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 formed
Prototype 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
- When called as an object method, points to that object
obj.b();
/ / points to obj ` - Called as a function method,
var b = obj.b; b();
// point to the global window. - Called as a constructor
var b = new Per();
// This points to the current instance object - Called as call with apply
obj.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
- Definition: Calls a function or method with a specified this value and several specified parameter values
- 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
- 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
- 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
- Application scenarios
Change the this pointer, mostly to borrow methods or attributes
-
- Determine the data type and borrow
Object
thetoString
methodsObject.prorotype.toString.call()
- Determine the data type and borrow
-
- Subclasses inherit superclass attributes,
function Chi() {Par.call(this)}
- Subclasses inherit superclass attributes,
4. apply
- Definition: Calls a function or method with a specified this value and an array containing specified parameter values
- 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
- 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
- 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
- Application scenarios
- With the call
5. bind
- 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
- 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
- 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
- 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
- Prototype chain inheritance and prototype inheritance
- You cannot pass parameters to the parent class. You can only share attributes
- Borrow constructors and parasitic inheritance
- Methods are not in the prototype and must be recreated each time
- Combination of inheritance
- Although the above two problems were solved, the father was called twice,
- The same properties are used for instance and prototype
- 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
- 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
- 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)
-
obj2 = Object.assign({}, obj1)
-
arr2 = [].concat(arr1)
-
arr2 = arr1.slice(0)
-
arr2 = Array.form(arr1)
-
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
- Time object => as a string
- RegExp, Error => returns empty objects
- The function, undefined = > lost
- NaN, Infinity, and -infinity => serialize to NULL
- Objects are generated by constructors => which discard the object constructor
- 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)
- 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
- 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
- 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,string
turndigital
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 +, ==
- When the operation
- The addition of a string exists by converting it to a string
- Multiply – divide – subtraction all strings go to numbers
- Equal comparison
- Boolean comparison, number first
- Comparing numbers to strings,
string
turndigital
- 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
- 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
- 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
- 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
- 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)
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
- 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:
- Timer execution and clearing
- Apply changes the this pointer
- 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
- 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
- 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
- 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
- Features:
Parameters of reuse
.Return early
.Delay the
- 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