Js data type
Basic type: Number String Boolean NULL undefined Symbol Bigint
Reference type: Object Function
Number
NaN: not a number is not a valid number, but is of type number
NaN is not equal to NaN itself, and is not equal to any other value
- IsNaN ([value]): Checks if the current value is not a valid number. Returns true if it is not a valid number and false if it is
- Object.is(NaN, NaN):true
-Leonard: Infinity. -Leonard: Infinity
Convert other data types to number
- Explicit conversion “Number ([value]) | parseInt/parseFloat ([value]) both the underlying processing rules are not the same as”
- Implicit conversion -> Number
- Mathematical operations
- Based on the == comparison
- isNaN([value])
- .
console.log(typeof NaN); //->'number'
console.log(typeof Infinity); //->'number'
console.log(NaN= = =NaN); //->false
console.log(Object.is(NaN.NaN)); //->true
Copy the code
String
Convert other values to strings
- Explicit: String([value]) or [value].toString() “-> Extend datatype detection”
- Implicit:
- In addition to math, the plus sign also produces string concatenation
let n = '10',
m = 10;
console.log(10 + n); // "+" appears on one side of the string "prerequisite: two sides" becomes string concatenation '1010'
console.log(+n); // "+" has only one side to convert the value to the number 10
console.log(++n); // "++" is converted to a number as above, but it adds up to 11 by itself
// I = I +1 I +=1 these are the same thing
// I ++/++ I is mostly the same as above, but if the value of I itself is a string, it is inconsistent.
// If either side of the "+" is an object, it may also be a string concatenation
/ / + 10 + {} or 10 + {name:} 'zhufeng' - > '10 [object object]'
// + 10+[10] ->"
/ / special:
// + 10+new Number(10) -> 20
/ / + + 10 {} or {name: 'XXX'} + 10 - > 10 "reason: {...} is not involved in operation, the browser believe that education is a code block, computing" + 10 ""
// + ({}+10) -> '[object Object]10'
// let x={}+10 -> '[object object]10
/ / +...Underlying mechanism: when an object is doing math// + check the object's Symbol. ToPrimitive property value, if there is, based on this value, if not
// + check the valueOf the object valueOf() for "primitive value: primitive type value", if there is a value based on this value, if not the original value
// + get the toString() of the object and turn it into a string -> If it is' + ', then you see a string, so it is string concatenation
// + convert the string to a number
// let obj = {};
// console.log(10 + obj); //->'10[object Object]'
let obj = {
[Symbol.toPrimitive]: function (hint) {
// hint: what type of default/string/number...
console.log(hint);
return 10; }};console.log(10 + obj); //20 hint->default
console.log(10 + new Number(10)); //20 new Number(10).valueOf() 10
console.log(Number(obj)) //10 hint->number
console.log(String(obj)) //'10' hint->string
Copy the code
Boolean
0 "" null undefined NaN ---> false
Copy the code
null undefined
console.log(null= =undefined) //true both and the other
Copy the code
Symbol() creates a unique value
// Assign a Symbol attribute to the object: unique attribute "reduce attribute handling conflicts"
// Macro manages some unique identifiers with unique values
// new Symbol(); //Uncaught TypeError: Symbol is not a constructor
// console.log(Symbol('AA') === Symbol('AA')); //->false
/* let obj = { [Symbol()]: 100 }; console.log(obj[Symbol()]); //->undefined */
/* let x = Symbol(); let obj = { [x]: 100 }; console.log(obj[x]); / / - > 100 * /
/* // Many JS built-in principles are based on the properties of these symbols to handle Symbol. ToPrimitive Symbol. HasInstance Symbol. * /
Copy the code
BigInt () of large Numbers
BigInt([num])
xxxn
// In large projects, large numbers may appear in the data returned by the server to the client. "The server database can store values based on longint, which may exceed the maximum safe number."
// number. MAX_SAFE_INTEGER: 9007199254740991 Maximum security Number
// Number.MIN_SAFE_INTEGER
// The result is inaccurate when the operation exceeds the safe number
Copy the code
Four data type conversion rules
Detection of data types
- typeof
- The result detected is a string
- Typeof NULL -> ‘object’ is not an object, but because the binary stored value begins with 000
- Detects the type of object subdivision that results in ‘object’
- instanceof
- constructor
- Object.prototype.toString.call([value])
/* * Convert other data types to Number type * 1. The specific need to convert to Number * + Number([val]) * + parseInt/parseFloat([val]) * 2. * + isNaN([val]) * + math (special case: * + When == is compared, some values need to be converted to numbers * +... *... * /
/* * Convert other data types to strings * 1. Can be used * + toString() * + String() * 2. ToString (); toString(); toString(); toString(); To go into digital * + based on alert/confirm/prompt/document. The write... These methods output content, all content is converted to a string, and then output * +... *... * /
1. You can convert other data types to Booleans * +! After converting to a Boolean value, the inverse * +!! Boolean([val]) * 2. Implicit conversion * + In loops and conditional judgments, the result of conditional processing is a Boolean value * +... * * rule: only '0, NaN, null, undefined, empty string' will be Boolean FALSE, the rest are TRUE */
* {}=={} : false Objects compare the address of heap memory * []==[] : false * NaN==NaN: Null ==undefined: true, null==undefined: true, null== = false, null/undefined is not equal to any other data type * 2. */ */ */ */ */ */ */ */ */
Copy the code
console.log([] == false) //true
// Object == booleans are converted to numbers (implicit conversion)
// toString to a number: toString is converted to a string, and toString to a number
// [] -> '' -> 0 false -> 0 true -> 1
console.log(! [] = =false) // true
/ /! [] -> false
/ / the other type is converted to a string, are generally not directly use "wrapped up, only {} ordinary Object Object to be obtained. The prototype. ToString, not converted to a string, but testing data types, return the result is' [Object Object] '
// Convert other types to numbers
/ / Number mechanism
console.log(Number(' ')) / / 0
console.log(Number('10')) / / 10
console.log(Number('10px')) // NaN Any non-valid numeric character is NaN
console.log(Number(true)) / / 1
console.log(Number(false)) / / 0
console.log(Number(null)) / / 0
console.log(Number(undefined)) // NaN
console.log(Number(Symbol(10))) / / an error
console.log(Number(BigInt(10))) / / 10
// Convert an object to a number, first valueOf, no original value, then toString to a string, and finally the string to a number
/ / the parseInt mechanism
// Starting at the first digit of the string, it looks for a valid digit character (stop when it sees an invalid digit character, regardless of whether there are any digits left), converts the found digit character to a digit, and returns NaN parseFloat that recognizes one more decimal point than parseInt if none is found
parseInt(' ') // NaN
Number(' ') / / 0
isNaN(' ') // false
parseInt(null) // NaN
Number(null) / / 0
isNaN(null) // false
parseInt('12px') / / 12
Number('12px') // NaN
isNaN('12px') // true
parseFloat('1.6 px.) + parseInt('1.2 px.) + typeof parseInt(null) / / '2.6 number'
isNaN(Number(!!!!!Number(parseInt('0.8 px.)))) // false
typeof !parseInt(null) +!isNaN(null) // 'booleantrue'
10 + false + undefined+ + []'Tencent' + null + true + {}
// 10 + false -> 10
// 10 + undefined -> NaN
// NaN + [] -> 'NaN'
// 'NaN' + 'Tencent' -> 'NaNTencent'
// 'NaNTencent' + null + true + {} -> 'NaNTencentnulltrue[object Object]'
10 + false + undefined + + 'Tencent' + null + true + {}
// 'NaN[object Object]'
// parseInt(value, [radix])
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
// Radix 2-36 does not result in NaN
// See value as radix
let arr = [10.18.0.10.25.23]
arr = arr.map(parseInt)
console.log(arr)
// parseInt('10.18', 0) // 10
// parseInt('0', 1) // NaN
// parseInt('10', 2) // 2
// parseInt('25', 3) // 2
// parseInt('23', 4) // 11
// parseInt(0xf) // 15
// parseInt(0xf, 16) // 21
Copy the code
Stack memory
Stack memory
/* var a = 12;
var b = a;
b = 13;
console.log(a);
var a = {n: 12};
var b = a;
b['n'] = 13;
console.log(a.n); */
/* var a = { n: 12 }; var b = a; b = { n: 13 }; console.log(a.n); * /
var a = {
n: 1
};
var b = a;
a.x = a = {
n: 2
};
console.log(a.x);
console.log(b);
// Normal operations are from right to left
/* a=b= XXX b= XXX a= XXX or a=b */
// a.x member access, operation priority is high
/* a.x=b=xxx b=a.x=xxx + a.x=xxx + b=xxx */
Copy the code
Function underlying processing mechanism (create + execute)
Function underlying processing mechanism (closure)
closure
Closure: A mechanism by which functions are run (not in some form of code)
- Function will create a new private context, if the context of certain content (generally refers to the heap memory address) to be context of some things (such as variable/event etc.), occupied the current context cannot be released in a stack (the browser’s garbage collection mechanism in the determination of GC) = > closure mechanism: forming a context is not released
- Protect: Protect private variables in a private context from the outside world
- Save: When the context is not freed, the private variables and values in the context are saved and made available to their subordinate contexts
- Cons: If you use a lot of closures, stack memory will be too large, page rendering will slow down, and performance will suffer, so you need to “use closures properly” in real projects; Some code can cause stack overruns or memory leaks, and these are things to watch out for.
// Loop event binding
1.closure2. let
3.Custom attributes4. Event delegationCopy the code
JS advanced programming skills
The use of closure mechanism, some of the implementation of high – order programming
- Modular thinking (singleton design pattern)
- The inertia function
- Cauchy function
- Compose combination function
- High order group price -> React
- Function anti-shake and throttling
- bind
- .
// Modular thinking
/ / the singleton - > AMD (the require. Js) - > CMD (sea. Js) - > CommonJS (Node) - > ES6Module
//--------- Before the idea of modularization, collaborative team development or large amount of code would lead to global variable pollution and "global variable conflict".
Var time = '2020-11-01'; function queryData() { // ... } function changeCity() { //... Var time = '2020-10-31'; function changeCity() { //... } * /
//-----------'s temporary closure based "protection" prevents contamination of global variables "but because each piece of code is private, it cannot be called to each other"
/* (function () { var time = '2020-11-01'; function queryData() {} function changeCity() {} })(); (function () { var time = '2020-10-31'; function changeCity() {} })(); * /
//---------- implements mutual calls based on some method
/* (function () { var time = '2020-11-01'; Function queryData() {} function changeCity() {} function queryData() {} function changeCity() {} "Window. queryData=queryData; }) (); (function () { var time = '2020-10-31'; function changeCity() {} queryData(); }) (); * /
//---------
// Object features: Each Object is a separate heap memory space (a separate instance ->Object), so that even if members in multiple objects have the same name, it does not affect each other
Obj1 /obj2 is not only called an object name, but also called a "namespace" to give the heap space a name.
Each object is a single instance, which is used to manage its own private information. Even if the name is the same, it does not affect each other. In fact, this is "JS singleton design pattern".
/* var obj1 = { name: 'zhufeng', age: 12, fn: function () {} }; var obj2 = { name: 'zhouxiaotian', age: 30, fn: function () {} }; * /
//---------- advanced singleton design pattern: the combination of closure + singleton, is also the earliest JS modular idea
/* var weatherModule=(function () { var time = '2020-11-01'; function queryData() {} function changeCity() {} return { queryData:queryData, changeCity:changeCity }; }) (); var infoModule=(function () { var time = '2020-10-31'; function changeCity() {} weatherModule.queryData(); return { changeCity:changeCity }; }) (); var skinModule=(function(){ // ... return {}; }) (); * /
Copy the code
// an inert function
// window.getComputedStyle(element) : Gets the browser-computed style of the current element.
// In IE6~8, this notation is not compatible. Use element. CurrentStyle
// "Property in object" checks whether the current object has this property and returns true if it does, false if it does
/* function getCss(element, attr) { if ('getComputedStyle' in window) { return window.getComputedStyle(element)[attr]; } return element.currentStyle[attr]; } var body = document.body; console.log(getCss(body, 'height')); console.log(getCss(body, 'margin')); console.log(getCss(body, 'background')); * /
//------- optimization idea: the first execution of getCss we already know whether compatible, the second and later again execute getCss, do not want to deal with compatible verification, in fact, this idea is "lazy" "lazy, dry a can be done, absolutely do not do the second time"
/* var flag = 'getComputedStyle' in window; function getCss(element, attr) { if (flag) { return window.getComputedStyle(element)[attr]; } return element.currentStyle[attr]; } * /
/* function getCss(element, attr) { If ('getComputedStyle' in window) {getCss = function getCss(element, attr) { return window.getComputedStyle(element)[attr]; }; } else { getCss = function getCss(element, attr) { return element.currentStyle[attr]; }; Return getCss(element, attr); return getCss(element, attr); } var body = document.body; console.log(getCss(body, 'height')); console.log(getCss(body, 'margin')); console.log(getCss(body, 'background')); * /
Copy the code
// Currization function
// The idea of pre-processing is to form an unreleased closure, store some information, access the pre-stored information later, based on the scope chain, and perform related processing. Anything that fits this pattern (or closure application) is called a kerochemical function.
// x: pre-stored value
/* function curring(x) { // x->10 return function (... Args) {// args->[20]/[20,30] args.unshift(x); Var total = eval(args.join('+')); return total; }; } * /
/* function curring(x) { return function (... args) { args.unshift(x); return args.reduce((result, item) => result + item); }; } var sum = curring(10); console.log(sum(20)); //10+20 console.log(sum(20, 30)); / / 10 + 20 + 30 * /
/* / array reduce method: Reduce ([callback],[initialValue]) var arr = [10, 20, 30, 40]; reduce([callback],[callback]) var arr = [10, 20, 30, 40]; /! * var res = arr.reduce(function (result, item, index) {// [initialValue] Reduce then iterates from the second item in the array // through each item in the array, // + result stores the result returned by the previous callback function (except for the initial value or the first item of the array) // + item currently traverses this item // + index index currently traverses this item console.log(result); return item + result; }); console.log(res); *! / var res = arr.reduce((result, item) => {return result + item; return result + item; }, 0); * /
/* Array.prototype.reduce = function reduce(callback, initial) { var self = this, // this->arr i = 0; if (typeof callback ! == "function") throw new TypeError('callback must be an function! '); if (typeof initial === "undefined") { initial = self[0]; i = 1; } // Iterate over each item in the array for (; i < self.length; i++) { var item = self[i], index = i; initial = callback(initial, item, index); } return initial; }; var arr = [10, 20, 30, 40]; var total = arr.reduce((result, item) => { return result + item; }); console.log(total); * /
Copy the code
/* One of the most important concepts in functional programming is function composition, which is essentially piping together functions that process data and then passing the data through the pipe to get the final result. For example, const add1 = (x) => x + 1; const mul3 = (x) => x * 3; const div2 = (x) => x / 2; div2(mul3(add1(0))); //=>3 For compose, we can construct a compose function that takes any number of functions as arguments (each of which takes a single argument), and then compose returns a function that does the following: const operate = compose(div2, mul3, Div2 (mul3(add1(0))) div2(mul3(add1(0))) Compose (f, g, h)(x) for compose(f, g, h)(x)
const add1 = x= > x + 1;
const mul3 = x= > x * 3;
const div2 = x= > x / 2;
// funcs: Stores the last function to be executed and its order (the function passed last takes precedence)
Compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose compose
// + returns a operate handler that executes operate and passes the initial value to execute the previously stored functions in the order in which they were executed
function compose(. funcs) {
return function operate(x) {
if (funcs.length === 0) return x;
if (funcs.length === 1) return typeof funcs[0= = ="function" ? funcs[0](x) : x;
return funcs.reduceRight(function (result, item) {
if (typeofitem ! = ="function") return result;
return item(result);
}, x);
};
}
var operate = compose(div2, mul3, add1);
var result = operate(0);
console.log(result);
/* var result = div2(mul3(add1(0))); console.log(result); / / - > 1.5 * /
/* // function compose(... funcs) { if (funcs.length === 0) { return arg => arg } if (funcs.length === 1) { return funcs[0] } return funcs.reduce((a, b) => (... args) => a(b(... args))) } */
Copy the code
Declare variables in js
- Tradition: Var function
- ES6: let const import
// let vs var
1.varThere is a variable promotion, andletThere is no2.Global contextvarThe declared variable is also equivalent to adding an attribute to GO, and when one value changes, another value changes (mapping mechanism), butletThe declared variable, the global variable, has nothing to do with GO3.In the same context,letCan't repeat the statement,varcan4.Temporary dead zones (browser temporary bugs)5. let/const/functionGenerates a block-level private context, whilevar/ * *EC(G) * Variable promotion:var n; * /console.log(n) //undefined
console.log(m) //Uncaught ReferenceError: Cannot access 'm' before initialization
var n = 12
let m = 13
let n = 12
console.log(n) / / 12
console.log(window.n) //undefined
var n = 12
console.log(n) / / 12
console.log(window.n) / / 12
window.n = 13
console.log(n) / / 13
n = 13 // window.n = 13 Not declared based on any keyword, which is equivalent to setting an attribute for window
console.log(n) //13 check whether it is a global variable, and if not, check whether it is an attribute of window
console.log(m) Uncaught ReferenceError: m is not defined
Before the code executes, browsers do a lot of things: lexical analysis, variable promotion
//' lexing phase ', error if repeated variable operations are found based on let/const
console.log('ok')
var n = 12
var n = 13
let n = 14
console.log(n) //Uncaught ReferenceError: n is not defined
console.log(typeof n) // Typeof detects an undeclared variable and does not error undefined
console.log(typeof n) //Uncaught ReferenceError: Cannot access 'n' before initialization
let n = 12
/* * context & scope * global context * Private context formed by function execution * block-level context (except object/function... For example, the judgment body if, the loop body for switch while, the code block {}) may produce block-level context */
{
var n = 12
console.log(n) / / 12
let m = 13
console.log(m) / / 13
}
console.log(n) / / 12
console.log(m) //Uncaught ReferenceError: m is not defined
for(var i=0; i<5; i++){console.log(i) // 0 1 2 3 4
}
console.log(i) / / 5
for(let i=0; i<5; i++){console.log(i) // 0 1 2 3 4
}
console.log(i) // Uncaught ReferenceError: i is not defined
let i = 0
for(; i<5; i++){console.log(i) // 0 1 2 3 4
}
console.log(i) / / 5
// The closure that the browser helped us form
for(let i=0; i<buttons.length; i++){// Parent block level context control loop
// The first loop contains the private block-level context EC(B1) I =0
// a small function created in the current context is occupied by the global button click, EC(B1) will not be released (closure)
buttons[i].onclick = function(){
console.log('Index of currently clicked button:${i}`)}// ...
}
// Can't implement, can't generate closure
let i = 0
for(; i<buttons.length; i++){ buttons[i].onclick =function(){
console.log('Index of currently clicked button:${i}`)}}Copy the code
Variable promotion mechanism
Variable promotion: In the current context (global/private/block level), the browser takes care of things before the JS code is executed top-down (which can be interpreted as a part of the lexical parsing, which must take place before the code is executed)
- All var and function keywords are declared or defined in advance
- Var advance declaration
- Function is declared and defined in advance
/* * Before code execution: global context variables are promoted * var a; The default value is undefined */
console.log(a) // undefined
var a = 12 // Create a value of 12 without declaring a(the variable promotion phase is complete, the completed things will not be reprocessed) a = 12 assignment
a = 13 // global variable A = 13
console.log(a) / / 13
/* * EC(G) variable promoted */
// window.a undefined
console.log(a) //Uncaught ReferenceError: a is not defined
a = 12
console.log(a)
/* * EC(G) variables improve let and const in ES6 without */
console.log(a) //Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 12
a = 13
console.log(a)
/* * Variables declared in the global context based on var and function (global variables) are mapped to a copy of GO (global object window) as its property, and the next change is followed by another change */
/* * a = 12 also sets the window attribute let and const */
Var a; /* * EC(G) var a; /* * EC(G) var a; * func = function * [new version] * var a; * func; * /
if(! ('a' in window)) {var a = 1
}
console.log(a) //undefined
Copy the code
Conclusion:
- The var and function keywords are declared or defined in advance
- Variables declared by var and function in the global context (global variables) are mapped to GO
- Conditions with function will only be declared in advance in newer browsers, not defined
- Browsers are lazy and don’t do what they did during variable promotion and code execution
fn() / / 5
function fn () {console.log(1)}
fn() / / 5
function fn () {console.log(2)}
fn() / / 5
var fn = function() {console.log(3)}
fn() / / 3
function fn () {console.log(4)}
fn() / / 3
function fn () {console.log(5)}
fn() / / 3
// Functions take precedence over variables
Var function = function ()
Copy the code
var foo = 1
function bar () {
if(! foo){var foo = 10
}
console.log(foo) / / 10
}
bar()
Copy the code
Problem set for closure scopes
Variable ascension
/* * EC(G) * var a; * var b; * var c; * fn = 0x000; [[scope]]:EC(G) */
console.log(a, b, c); //=>undefined * 3
var a = 12,
b = 13,
c = 14;
function fn(a) {
EC / * * * (FN) private context scope chain: < EC (FN), EC (G) > * parameter assignment: a = 10 * variables: - * /
console.log(a, b, c); / / = > 10 13 14
a = 100;// Private a is assigned to 100
c = 200;// assign global c to 200
console.log(a, b, c); / / = > 100 to 13, 200
}
b = fn(10);// assign global b to undefined
console.log(a, b, c); //=>12 undefined 200
Copy the code
/* * EC(G) * var I; * A = 0x000; [[scope]]:EC(G) * var y; * B = 0x001; [[scope]]:EC(G) */
var i = 0;
function A() {
EC / * * * (A) private context scope chain: < EC (A), EC (G) > * parameter assignment: - * variables: * var I; * x = 0x002; [[scope]]:EC(A) */
var i = 10;
function x() {
EC / * * * (X1) private context scope chain: < EC (X1), EC (A) > * parameter assignment: - * variables: - * /
EC / * * * (X2) private context scope chain: < EC (X2), EC (A) > * parameter assignment: - * variables: - * /
console.log(i);
}
return x; //return 0x002;
}
var y = A(); //y=0x002;
y(); / / = > 10
function B() {
EC / * * * (B) private context scope chain: < EC (B), EC (G) > * parameter assignment: - * variables: * var I; * /
var i = 20;
y();/ / = > 10
}
B();
Copy the code
/* * EC(G) * var a; * var obj; * fn = 0x000; [[scope]]:EC(G) */
var a = 1;
var obj = {
name: "tom"
}; //obj=0x001
function fn() {
/ EC (FN) * * * scope chain: < EC (FN), EC (G) > * parameter assignment: - * variables: var a2; * /
var a2 = a; / / private a2 = 1
obj2 = obj;
//obj2 is not private, look globally, if not globally
Uncaught ReferenceError: obj2 is not defined
// Case 2: The assignment operation is equivalent to setting an obj2 property for window and assigning window.obj2=0x001
a2 = a; / / private a2 = 1
obj2.name = "jack"; // If obj2 does not exist globally, it will continue to check if the property exists under window. If the property exists under window, it will get the value of the property. If the property does not exist under window, it will report an error (undefined variable) -> Change the name property in 0x001 to 'jack'.
}
fn();
console.log(a);/ / = > 1
console.log(obj);//=>{name:'jack'}
/* // VO(G): console.log(a); // GO "window" : console.log(a); A is not defined */ a is not defined */
Var n = 10; var n = 10; VO(G) specifies a global variable of n and assigns 10; Special: in the "global context", "based on var/function declaration" variable, also equivalent to add private attributes to GO; And there is a mapping relationship between "one modification, the other is also modified"; // New version of the mechanism: in "global context", "var/function declaration" variables are directly stored as GO attributes; console.log(n); //=>10 console.log(window.n); //=>10 m = 10; M -> window.m=10 console.log(m); //=>10 console.log(window.m); / / = > 10 * /
/* // set VO(G) as a global variable with no relation to GO; let n = 10; console.log(n); //=>10 console.log(window.n); //=>undefined */
Copy the code
/* * EC(G) * var a; * fn=0x000; [[scope]]:EC(G) */
var a = 1;
function fn(a) {
/ EC (FN) * * * scope chain: < EC (FN), EC (G) > * parameter assignment: a = 1 * variables: * var a; * a=0x001; * a=0x001; [[scope]]:EC(FN) "not repeated, but reassigned" */
console.log(a); / / = > function
var a = 2; // Private a is reassigned to 2
function a() {}
console.log(a); / / = > 2
}
fn(a); //fn(1)
console.log(a); / / = > 1
Copy the code
/* * EC(G) * var a; * fn=0x000; [[scope]]:EC(G) */
console.log(a); //=>undefined
var a = 12;
function fn() {
/ EC (FN) * * * scope chain: < EC (FN), EC (G) > * parameter assignment: - * variables: var a; * /
console.log(a); //=>undefined
var a = 13;
}
fn();
console.log(a); / / = > 12
Copy the code
/* * EC(G) * var a; * fn=0x000; [[scope]]:EC(G) */
console.log(a); //=>undefined
var a=12;
function fn(){
/ EC (FN) * * * scope chain: < EC (FN), EC (G) > * parameter assignment: - * variables: - * /
console.log(a); / / = > 12
a=13;
}
fn();
console.log(a); / / = > 13
Copy the code
/* * EC(G) * fn=0x000; [[scope]]:EC(G) */
console.log(a); // Uncaught ReferenceError: A is not defined
a=12;
function fn(){
console.log(a);
a=13;
}
fn();
console.log(a);
Copy the code
/* * EC(G) var foo; * /
var foo = 'hello';
(function (foo) {
EC (AN) / * * * scope chain: < EC (AN), EC (G) > * parameter assignment: foo = 'hello' * variables: var foo. * /
console.log(foo); //=>'hello'
var foo = foo || 'world';
/ / A | | A if B is false returns the value of B, A true return A value
// A &&b A returns the value of A if false, and B if true
/ / exist && priority than | |
console.log(foo); //=>'hello'
})(foo); // The self-executing function executes, passing in the value "hello" of global foo as an argument
console.log(foo); //=>'hello'
Copy the code
Mechanism of abnormal condition
console.log(foo); //undefined
{
console.log(foo); / / function
function foo() {}
foo = 1;
console.log(foo); / / 1
}
console.log(foo); / / function
Copy the code
/* * EC(G) * function foo; * function foo; * /
console.log(foo); //=>undefined
{
/* * EC(B) variable promotion * foo = 0x000; * foo = 0x001; * /
console.log(foo); //=>0x001
function foo() {0} // special: all previous operations on foo give the global a copy of global foo=0x001
console.log(window.foo); //=>0x001
foo = 1;
function foo() {1} // special: all previous operations on foo give the global a copy of global foo=1
console.log(foo); / / = > 1
}
console.log(foo); / / = > 1
Copy the code
{
function foo() {}
foo = 1;
function foo() {} // special: all previous operations on foo are given a global copy
foo = 2;
}
console.log(foo); / / = > 1
Copy the code
var x = 1;
function func(x, y = function anonymous1(){x = 2}){
x = 3;
y();
console.log(x); / / 2
};
func(5);
console.log(x); / / 1
Copy the code
var x = 1;
function func(x, y = function anonymous1(){x = 2}){
var x = 3;
y();
console.log(x); / / 3
};
func(5);
console.log(x); / / 1
Copy the code
var x = 1;
function func(x, y = function anonymous1(){x=2}){
var x = 3;
var y = function anonymous2(){x = 4}
y();
console.log(x); / / 4
};
func(5);
console.log(x); / / 1
Copy the code
/* * arr.map((item,index)=>{ * return xxx; *}) -> Array iteration method * * parseInt(XXX) : Convert XXX to a string, then search from the first character to the left of the string, find a valid digit character "until you encounter a non-valid digit character", convert the found valid digit character to a number! * parseInt (XXX, radix) : Radix radix, from left to right in the XXX string, find the information that accord with the radix, convert the found result to 10 base * RADIX: the value range is between 2 and 36, if not, the final result is NaN * radix: not set or set to 0, The default is base 10. "Special: if the string starts at 0x, the default is not 10, but 16" */
/* let arr = [27.2, 0, '0013', '14px', 123]; arr = arr.map(parseInt); // parseInt(27.2) -> parseInt('27.2') -> 27 // parseInt(0,1) -> NaN // parseInt('0013',2) -> '001' converts found binary to decimal // 1 * 2 * 2 ^ ^ 0 + 0 1 + 0 * 2 ^ 2 = > 1 + 0 / + 0 = > 1 / parseInt (' 14 px, 3) - > '1' to find three hexadecimal conversion for decimal / / 1 * 3 ^ 0 = > 1 / / parseInt (123, 4) - > ParseInt ('123',4) -> '123' converts found base 4 to base 10 // 3*4^0 + 2*4^1 +1 *4^2 =>3+8+16 =>27 console.log(arr); * /
parseInt(070)
// if a number starts with 0, the browser interprets it as base 8 and converts it to decimal
// 0*8^0 + 7*8^1 + 0*8^2 =>56
// parseInt(56) -> parseInt('56',10) */
Copy the code
var a = 4
function b(x, y, a) {
console.log(a) / / 3
arguments[2] = 10
console.log(a) / / 10
}
a = b(1.2.3)
console.log(a) //undefined
Copy the code
function fn(x, y, z) {
// ARGUMENTS: {0:1,1:2,length:2}
// Parameter assignment: x=1, y=2, z=undefined
// "ARG[0]:x ARG[1]:y"
arguments[0] =10;
console.log(x); / / 10
y=20;
console.log(arguments[1]); / / 20
// The mapping mechanism is not established at the beginning, and it does not matter how it is handled later
console.log(z); //undefined
arguments[2] =30;
console.log(z); //undefined
}
fn(1.2);
Copy the code
// Assign the result returned by the self-executing function to test
// test=0x001;
var test = (function (i) {
/ EC (AN) "closure" * * * scope chain: < EC (AN), EC (G) > * parameter assignment: I = 2 * variables: - * /
return function () {
/ EC (TEST) * * * scope chain: < EC (TEST), EC (AN) > * initial ARGUMENTS: {0:5, length: 1} * parameter assignment: - * variables: - * /
alert(i *= 2); // let I in EC(AN) multiply by 2 =>"4"
}; //return 0x001; [[scope]]:EC(AN)}) (2);
test(5);
Copy the code
// the value passed by func is useless
var x = 4;/ / 3 2 1
function func() {
return function (y) { //0x001 0x002
console.log(y + (--x)); //x is global
};
}
var f = func(5); //f=0x001
f(6); / / = > 9
func(7) (8); //0x002(8) =>10
f(9); / / = > 10
console.log(x); / / = > 1
Copy the code
var x = 5,
y = 6;
function func() {
/ EC (F1) * * * scope chain: < EC (F1), EC (G) > * parameter assignment: - * variables: - * /
x += y; // change global x=11
func = function (y) { // global func=0x001 [[scope]]:EC(F1)
/ EC (F2) * * * scope chain: < EC (F2), EC (F1) > * parameter assignment: y = 3 * variables: - * /
console.log(y + (--x)); // if x=10 =>13
};
console.log(x, y); / / = > 11 June
}
func(4);
func(3);
console.log(x, y); / / = > 10 6
Copy the code
/ / = = = = = = = = = = = = = = = my homework
// Briefly describe your understanding of closures and their advantages and disadvantages. "Play"
// + Basic introduction: ECStack, EC, VO, AO, GO, SCOPE, scope-chain, GC
// + save and protect, performance consumption (memory leak)
// + +
// + loop event binding "highlight: event delegate", LET and VAR
// + plug-in component package: JS advanced programming skills "singleton design pattern, inert function, kerochemistry function, compose composite function"
Redux, redux, redux, redux, redux...
/ / +...
// + own thoughts and understanding "in a word"
// Summarize a 5min or so of words, the answer process refused to "endorsement" answer, some popular, arrange some scenes...
// Tip: You can also write an essay detailing closures: "Show them to the interviewer during the interview. They will look at you and say a few words."
/ / = = = = = = = = = = = = = = = my homework
// What is the difference between let and var?
// + variable promotion
// + repeat the declaration
// declare the relationship with GO globally
// + temporary dead zone "highlights the role of" Typeof detects an undeclared variable and results in undefined "-> encapsulates plug-in components"
// + block level scope
// + ...
Copy the code
// Anonymous function "nomenclature" : this is a specification
// const func = function func() {};
// document.body.onclick = function bodyclickhandle() {};
// (function anonymous(){})();
/ /...
// + anonymous function nominalization, set the name of a variable that is not in the current function's scope
/* (function b() {})();
console.log(b); //Uncaught ReferenceError: b is not defined */
// + function names can only be used inside functions: the nice thing is that anonymous functions can also be called recursively "strictly disallow arguments.callee"
/* "use strict"; (function b() { console.log(b); //=> the function itself console.log(arguments.callee); //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them })(); * /
// + and inside the function, directly changing its value is also invalid
/* (function b() { b = 10; console.log(b); / / = >}) () function; * /
Var /let/const/function can be changed unless the function redeclares the variable internally: var/let/const/function
/* (function b() { let b = 10; console.log(b); / / = > 10}) (); * /
var b = 10;
(function b() {
/* b = 20; console.log(b); * / / / = > function
let b = 20;
console.log(b); / / = > 20}) ();console.log(b); / / = > 10
/* var b = 10; Function b(b) {function b(b) {function b(b) { However, once declared in any way, it is treated as a variable, regardless of the function name; console.log(b); / / = > twenty (20)}); console.log(b); * /
Copy the code
function fn(. outerArgs) {
return function anonymous(. innerArgs) {
return outerArgs.concat(innerArgs).reduce(function handle(result, item) {
return result + item;
}, 0);
};
}
const fn = (. outerArgs) = > (. innerArgs) = > outerArgs.concat(innerArgs).reduce((result, item) = > result + item, 0);
let res = fn(1.2) (3);
console.log(res);
Copy the code
var num = 10; //window.num=10
var obj = {
num: 20
}; //obj=0x000;
obj.fn = (function (num) {
EC (AN) / * * * "closure" scope chain: < EC (AN), EC (G) > * initial THIS: Windows * parameter assignment: num = 20 / / - > 21, 22, 23 * variables increases: - * /
this.num = num * 3; //window.num=num*3=60
num++;
return function (n) {
/ * * EC (FN1) - > fn (5) * scope chain: < EC (FN1), EC (AN) > * initial THIS: Windows * parameter assignment: n = 5 * variables: - * /
/ * * EC (FN2) - > obj. Fn (10) * scope chain: < EC (FN2), EC (AN) > * initial THIS: obj * parameter assignment: n = 10 * variables: - * /
this.num += n; //window.num=window.num+n=65 obj.num=obj.num+n=30
num++;
console.log(num); / / = > 22, 23
}; //obj.fn=0x001; [[scope]]:EC(AN)
})(obj.num);
var fn = obj.fn; //fn=0x001;
fn(5);
obj.fn(10);
console.log(num, obj.num); / / = > 30 65
Copy the code
// THIS is the name of the function. It doesn't matter where the function is defined or executed
let obj = {
fn: (function () {
return function () {
console.log(this);
} //obj.fn=0x000;()}}); obj.fn();//=>obj
let fn = obj.fn; //fn=0x000;
fn(); //=>window
Copy the code
var fullName = 'language'; //window.fullName='language';
var obj = {
fullName: 'javascript'.prop: {
getFullName: function () {
return this.fullName; }}};console.log(obj.prop.getFullName());
//=>this:obj.prop =>obj.prop.fullName =>undefined
var test = obj.prop.getFullName;
console.log(test());
//=>this:window =>window.fullName =>'language'
Copy the code
var name = 'window'; //window.name='window'
var Tom = {
name: "Tom".show: function () {
// this->window
console.log(this.name); //=>'window'
},
wait: function () {
// this->Tom
var fun = this.show; fun(); }}; Tom.wait();Copy the code
window.val = 1;
var json = {
val: 10.dbl: function () {
this.val *= 2;
}
}
json.dbl();
//->this:json ->json.val=json.val*2 ->json.val=20
var dbl = json.dbl;
dbl();
//->this:window ->window.val=window.val*2 ->window.val=2
json.dbl.call(window);
//->this:window ->window.val=window.val*2 ->window.val=4
alert(window.val + json.val); / / = > "24"
Copy the code
(function () {
var val = 1; / / - > 2
var json = {
val: 10.dbl: function () {
// this->json
val *= 2; //val=val*2 where val is a variable json}}; json.dbl(); alert(json.val + val);/ / = > "12"}) ();Copy the code
curring
/* function add(... params) { const proxy = (... Params = params.concat(args); params = params. return proxy; }; Proxy.tostring = () => {// Call function toString implicitly based on function operation or output, Return params.reduce((result, item) => result + item); }; return proxy; } * /
function curring() {
let params = [];
let add = function (. args) {
params = params.concat(args);
return add;
}
add.toString = function () {
return params.reduce((result, item) = > result + item);
};
return add;
}
let add = curring();
let res = add(1) (2) (3);
console.log(res); / / - > 6
add = curring();
res = add(1.2.3) (4);
console.log(res); / / - > 10
add = curring();
res = add(1) (2) (3) (4) (5);
console.log(res); / / - > 15
ToString function fn() {} fn.toString = function () {console.log('OK'); }; // console.log(fn + 1); / / will, in turn, obtaining the fn Symbol. The toPrimitive/the valueOf toString these three attributes console. The log (fn); * /
Copy the code
/* * Functions for debounce and throttle * * in "high frequency" triggered scenarios that require buffering and throttling * + press a button * + page scroll * + input fuzzy matching * +... * We set ourselves how long it takes for two or more triggers to be considered as "high frequency" : when encapsulating the method, we need to specify this frequency (you can set the default value) * "Anti-shake" in a certain high frequency trigger, we only identify once (can control the start of the trigger, or the last trigger); Details: Suppose we stipulate that 500MS triggering multiple times is considered as high frequency, as long as we detect that it is triggered by high frequency, it will only trigger once in this frequent operation (even if you operate for 10min)... * When "throttling" is triggered at a certain high frequency, we do not only recognize it once, but also trigger it once if the frequency is not reached according to the interval we set (the frequency specified by ourselves). Detail: Suppose we specify a frequency of 500MS, we operate for 10min, the number of triggers =(10*60*1000)/500 */
function debounce(func, wait, immediate) {
// Multiple parameters and pass default handling
if (typeoffunc ! = ="function") throw new TypeError("func must be an function!");
if (typeof wait === "undefined") wait = 500;
if (typeof wait === "boolean") {
immediate = wait;
wait = 500;
}
if (typeofimmediate ! = ="boolean") immediate = false;
// Set the timer return value identifier
let timer = null;
return function proxy(. params) {
let self = this, now = immediate && ! timer;clearTimeout(timer);
timer = setTimeout(function () {
timer = null; ! immediate ? func.call(self, ... params) :null;
}, wait);
// Execute immediately on the first triggernow ? func.call(self, ... params) :null;
};
}
/* function handle(ev) {console.log('OK', this, ev); } submit.onclick = debounce(handle, true); // submit.onclick = proxy; // submit. Onclick = handle; // submit. //handle->this:submit Passes an event object */
// Tip 1 for business scenarios: Identification is similar to throttling
/* let flag = false; submit.onclick = function () { if (flag) return; flag = true; console.log('OK'); SetTimeout (() => {// the thing is done flag = false; }, 1000); }; * /
Function handle() {submit.onclick = null; submit.disabled = true; / /... console.log('OK'); setTimeout(() => { submit.onclick = handle; submit.disabled = false; }, 1000); } submit.onclick = handle; * /
function throttle(func, wait) {
if (typeoffunc ! = ="function") throw new TypeError("func must be an function!");
if (typeof wait === "undefined") wait = 500;
let timer = null,
previous = 0; // Record the last operation time
return function proxy(. params) {
let self = this,
now = new Date(), // The current trigger operation time
remaining = wait - (now - previous);
if (remaining <= 0) {
// If the interval is longer than wait, execute it directly
clearTimeout(timer);
timer = null; previous = now; func.call(self, ... params); }else if(! timer) {// If the interval between two triggers does not exceed wait, the timer is set and the remaining timer is executed once after remaining.
timer = setTimeout(function () {
clearTimeout(timer);
timer = null;
previous = new Date(a); func.call(self, ... params); }, remaining); }}; }function handle() {
console.log('OK');
}
window.onscroll = throttle(handle, 500);
// window.onscroll = proxy;
/* window.onscroll = function () {// By default, the page is scrolling: In the shortest possible response time (4-6 ms), the browser recognizes that it is listening for an event and executes the bound method, resulting in too many times of method execution and unnecessary waste of resources console.log('OK'); }; * /
Copy the code
If JS is running in A browser or webview, A=window; if JS is running in A Node environment, A=global or the current module
var A = typeof window! = ="undefined" ? window : this;
// Callback function: pass a function as an argument to another function, and execute the passed function during execution
var B = function (window, noGlobal) {
// in the browser environment
// window=window
// noGlobal=undefined
"use strict";
var jQuery = function (selector, context) {
/ /...
};
var _jQuery = window.jQuery,
_$ = window. $; jQuery.noConflict =function (deep) {
if (window.$ === jQuery) {
window. $= _ $; }if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}
return jQuery;
};
// Support AMD modular thought require.js
if (typeof define === "function" && define.amd) {
define("jquery"[],function () {
return jQuery;
});
}
// in the browser environment
if (typeof noGlobal === "undefined") {
// Expose private methods to global objects
window.jQuery = window.$ = jQuery; }};// Self-executing function
(function (global, factory) {
"use strict";
if (typeof module= = ="object" && typeof module.exports === "object") {
Node.js /webpack is not supported by browsers by default.
// ...
} else {
// Browser or WebView environment
// -> B(window)
factory(global);
}
})(A, B);
/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = =
(function () {
function ModalPlugin() {}
// ...
// Prevent conflict handling
var _M = window.M;
ModalPlugin.noConflict = function noConflict() {
if (window.M === ModalPlugin) {
window.M = _M;
}
return ModalPlugin;
};
// Exposed API: supports browser "direct SCRIPT import" && CommonJS "support in webpack or ES6Module import"
if (typeof window! = ="undefined") {
window.M = window.ModalPlugin = ModalPlugin;
}
if (typeof module= = ="object" && typeof module.exports === "object") {
module.exports = ModalPlugin;
}
})();
Copy the code
Several cases of this
- event
// Whether DOM0 or DOM2 level event binding, bind method to some event behavior of element E. When the event triggers method execution, this in method is the current element E itself
In IE6~8, DOM2 event binding is implemented based on attachEvent, and the event triggers the execution of the method. This in the method is not the element itself, most cases are window 2. If call/apply/bind forces a change to this in a function, we will force the change
document.body.onclick = function () {
console.log(this);
};
document.body.addEventListener('click'.function () {
console.log(this);
});
Copy the code
- Ordinary function execution
// If the function is preceded by "dot", "dot", "this" is the same as "this", "this is window", "JS strictly mode undefined"
// fn() -> this:window/undefined
// obj.fn() -> this:obj
// xxx.__proto__.fn() -> this:xxx.__proto__
// Self-executing function execution: this is usually window/undefined
// This is also window/undefined unless special handling is done
// This in parentheses is abnormal
/* function fn() { console.log(this); } var obj = { name: 'zhufeng', fn: fn }; fn(); //this->window obj.fn(); //this->obj (obj.fn)(); //this->obj (fn, 10, obj.fn)(); //this->window */ this->window */
// var obj = {
// num: (function () {
// // assigns the return value of the self-executing function to the obj.num member
// console.log(this); //->window
// return 10;
/ /}) ()
// };
// Callback function: pass a function as a value to another function, and execute the function passed in from another function.
// var obj = {
// name: 'zhufeng'
// };
// setTimeout(function () {
// console.log(this); //->window
// }, 1000);
// [10].forEach(function () {
// console.log(this); //->window
// });
// [10].forEach(function () {
// console.log(this); //->obj
// }, obj);
Copy the code
- Constructor execution
- Arrow function execution
// The arrow function does not have its own this; it uses this in its context
// Run javascript code on the browser side. This is usually a window in a non-function; To study this is to study this in functions; In ES6+, block level context has no this of its own.
let obj = {
n: 0.fn() {
// this->obj
/* let self = this; setTimeout(function () { // console.log(this); //this->window self.n++; }, 1000); * /
setTimeout(() = > {
// this -> this -> obj
this.n++;
}, 1000); }}; obj.fn();Copy the code
- Force changes to this based on call/apply/bind
// prototype: call/apply/bind; // prototype: call/apply/bind
/* Function.prototype.call = function call(context) { // ... }; * /
function fn(x, y, ev) {
console.log(this, x, y, ev);
}
let obj = {
name: 'zhufeng'
};
// obj.fn(); //Uncaught TypeError: obj. Fn is not a function obj. Fn cannot change this in fn based on obj
// ==BIND== does not execute the function immediately, it preempts the function's THIS and arguments
// document.body.onclick = fn; THIS->BODY => THIS: BODY x:MouseEvent y:undefined
// document.body.onclick = fn(); //-> execute fn immediately, take the result of its execution as a value, assign the value to the event binding, event trigger execution is returned result
// Requirement: When you hit BODY, execute FN and make THIS->OBJ and pass 10/20 to X/Y
// document.body.onclick = fn.call(obj, 10, 20); // This does not work: call/apply executes functions immediately before they are clicked
/* document.body. Onclick = function (ev) { Call (obj, 10, 20, ev); call(obj, 10, 20, ev); }; * /
// document.body.onclick = fn.bind(obj, 10, 20);
// ==CALL/APPLY== both execute the function immediately, change THIS in the function, and pass parameter information to the function
/* fn.call(obj, 10, 20); // 1. Fn instance finds Function. Prototype call method based on __proto__, Call (); // Call (); // Call (); // Call () Context :obj // Call this to obj, and pass the rest of the parameters to fn */
// fn.call(undefined); // In non-strict mode, context is not passed or null/undefined, so this is changed to window; In strict mode, undefined is not passed; otherwise, this is changed to whoever is passed.
// fn.call(10, 20); //this->Number{10} x->20 y->undefined
// fn.apply(obj, [10, 20]); //this->obj x->10 y->20; // This ->obj x->10 y->20; // This ->obj x->10 y->20 I'm passing these parameters to FN one by one
// Call performs better than Apply, especially when passing three or more parameters
Copy the code
// Get the maximum value in the data
// let arr = [10, 13, 24, 15, 26, 34, 11];
/* arr.sort((a, b) => b - a); Console. log(' the maximum in the array is: ${arr[0]} '); * /
/* console.log(Math.max(arr)); //NaN console.log(Math.max(10, 13, 24, 15, 26, 34, 11)); //34 console.log(Math.max(... arr)); 34 * / / /
/* let max = Math.max.apply(Math, arr); // The arguments passed to the method using apply are console.log based on the array (' the maximum value in the array is: ${Max} '); * /
/* let max = 0; arr.forEach(item => { item > max ? max = item : null; }); Console. log(' the maximum in the array is: ${Max} '); * /
/* let max = eval(`Math.max(${arr})`); Console. log(' the maximum in the array is: ${Max} '); * /
// Need: summation of any number of arguments passed in
/* function sum(... params) { // params->[...] Return params.reduce((result, item) => {return result + item; }, 0); } * /
/* Array.prototype.slice = function slice() { // this->arr let params = []; for (let i = 0; i < this.length; i++) { params.push(this[i]); } return params; }; let arr = [10, 20, 30]; let params = arr.slice(); // clone arr */
function sum() {
// Arguments class Array, not Array, can't use Array methods (only Array instances can be called directly)
// 1. Convert the class array to an array
/* let params = Array.from(arguments); let params = [...arguments]; * /
/* let params = []; for (let i = 0; i < arguments.length; i++) { params.push(arguments[i]); } * /
/ / duck type: long like a duck in addition to call it a duck - > type Array __proto__ is not an Array. The prototype, its structural characteristics and an Array of basic "normal operation treatment is the same, such as: cycle..." -> Let the class array borrow the methods on the array prototype to implement some specific processing
let params = [].slice.call(arguments);
// Array.prototype.forEach.call(arguments, item => {});
// ...
/ / 2. Sum
return params.length === 0 ? 0 : eval(params.join('+'));
}
let total = sum();
console.log(total); / / - > 0
total = sum(10);
console.log(total); / / - > 10
total = sum(10.20);
console.log(total); / / - > 30
total = sum(10.20.30);
console.log(total); / / - > 60
Copy the code
* + context. XXX = THIS obj. Fn =fn; * + context. XXX = THIS obj. * + context.xxx() obj.fn(); * /
Function.prototype.call = function call(context, ... params) {
/ / this - > fn context - > obj params - > [10, 20]
context == null ? context = window : null;
Context must be a value of object type: only objects can set properties
!/^(object|function)$/.test(typeof context) ? context = Object(context) : null;
let self = this,
result = null,
key = Symbol('KEY'); // Add attribute names to ensure uniqueness and prevent contamination of members of the original objectcontext[key] = self; result = context[key](... params);delete context[key]; // Remove your new attributes when finished
return result;
};
function fn(x, y) {
console.log(this, x, y);
}
let obj = {
name: 'zhufeng'.fn: 100
};
fn.call(0.10.20);
/*
* 重写内置BIND:柯理化思想「预处理思想」
*/
Function.prototype.bind = function bind(context, ... outerArgs) {
/ / this - > fn context - > obj outerArgs - > [10, 20]
let self = this;
return function (. innerArgs) {
// innerArgs->[ev]self.call(context, ... outerArgs.concat(innerArgs)); }; };function fn(x, y, ev) {
console.log(this, x, y, ev);
}
let obj = {
name: 'zhufeng'
};
/* document.body.onclick = function (ev) { fn.call(obj, 10, 20, ev); }; * /
document.body.onclick = fn.bind(obj, 10.20);
Copy the code