preface
If your understanding of functions is somewhat vague, let’s eliminate it now
define
Anonymous functions
function (){
return 1
}
Copy the code
Function statements require a Function name Function statements require a Function name
// It is an anonymous function but it has a name
let fn = function (){
return 1
}
Copy the code
Fn records the address of the function in the stack. Fn records the address of the function in the stack
let fn2 = fn
Copy the code
So fn and fn2 refer to that function, so the following print is fn, the name of the anonymous function which by default is the same as the name of your variable
A named function
A function with a name
// The name fn3 is a variable whose scope is that fn3 can be accessed anywhere
function fn3(){
return 3
}
/ / for
**function fn4(){}** function fn4(){}**
let fn5 = function fn4(){}
// console.log(fn4) Beyond this section you cannot access Fn4
Copy the code
Arrow function
// There is only one argument
const$=s= > document.querySelector(s)
$('div')
// Two parameters
let fn6 = (x, y) = > x+y
// If there are more than one sentence, use curly braces to enlarge them and make clear the value of return
let fn7 = (x, y) = > {
console.log(1)
return x+y // There is no need to write return when there is only one sentence
}
Copy the code
Lexical scope (static scope)
var global1 = 1
function fn1(param1){
var local1 = 'local1'
var local2 = 'local2')
function fn2(param2){
var local2 = 'inner local2' Row 6, this is local2
console.log(local1)
console.log(local2)
}
function fn3(){
var local2 = 'fn3 local2'
fn2(local2)
}
}
Copy the code
Code analysis aboveWhen we print local1 in fn2, it prints local1 as determined by the lexical tree
There’s no local1 in fn2, so I’m going to look for it in fn1, so I’m going to find local1
A lexical tree analysis shows that local2 is local2 in my sixth line above, and has nothing to do with executing the sequence
Note ⚠️ : the lexical tree is only used to analyze whether the printed variable local2 is the same variable local2 inside the scope. It has nothing to do with values, but semantics. Whether their values are equal is not my concern
The interview questions
var a = 1
function b(){
console.log(a) // Is this a outside of my A? Certainly by lexical tree analysis, but does the value of a in any case print out as 1?
}
Copy the code
Suppose I change it to the following code
var a = 1
function b(){
console.log(a)
}
a = 2
b() // Print out 2
Copy the code
Lexical scope, which determines the relationship between two variables, does not care about their values
Read the following article for more details
- Javascript lexical scope
- Static and dynamic scopes
- Abstract Syntax Tree Introduction to Abstract Syntax Tree
Call Stack
The nested calls
recursive
The above two examples, last in, first out, completely show the execution timing of the function call stack
- JS engine before calling a function
- You need to push the function’s environment into an array
- This array is called the call stack
- When the function is done, it pops out the environment
- Then return to the previous environment and continue with the subsequent code
this & arguments
This & arguments, for each function except the arrow function, arguments is a pseudo-array containing all arguments
- This is the first argument to be hidden and must be an object
function f(){
console.log(this)
console.log(arguments)}// If you pass null or undefined, the default is to print window (in strict mode default is undefined).
f.call() // window
f.call({name:'hone'}) // {name: 'hone'}, []
f.call({name:'hone'},1) // {name: 'hone'}, [1]
f.call({name:'hone'},1.2) / / {name: 'hone'}, [1, 2]
Copy the code
- This article explains why the first parameter is a hidden parameter
- Why must it be an object
When I write f.call(10, 1), it’s the same thing as the new Number(10).
So why is that? Because this is the connection between the function and the object
If there is no this
let persion = {
name: 'hone'.'sayHi':sayHi
}
let sayHI = function (){
console.log('Hello, my name is.' + person.name)
}
Copy the code
Analysis of the
- If Persion is renamed, the sayHi function is invalid
- The sayHi function might even be in another file
- It has strong coupling, so we don’t want persion references in sayHi
class Persion {
constructor (name) {this.name = name // This is mandatory for new
}
sayHi(){
console.log('????? ')}}Copy the code
Analysis of the
- There is only the class and no object has been created, so it is impossible to get a reference to the object
- How do I get the name of the object? You need a way to get it, using parameters
The following are hypothetical objects
let persion = {
name: 'hone'.sayHi: function(persion){
console.log('Hi, I am ' + persion.name)
}
}
persion.sayHi(persion)
Copy the code
class
class Persion{
constructor(name){
this.name = name
}
sayHi(p){
console.log('Hello, my name is.'+ p.name)
}
}
Copy the code
Python takes this approach
This is used to solve the problem of not passing a value. I also know what the current object is passing. That thing, no. That’s Window
// The following two are equivalent
persion.sayHi()
person.sayHi.call(person) // Make it easy to tell the code reader what this is
Copy the code
aplay
let array = [1.2.3.4.5]
function sum(){
let n = 0
for(let i = 0; n < arguments.length; i++){
n += arguments[i]
}
}
// Arguments cannot be written if they are not sure how many arguments are used
// Hence the invention of apply
sum.apply(undefined, array)
Copy the code
Call and apply are almost exactly the same. You use apply when you are unsure of the number of arguments, or even if you know the length
bind
Introduction to bind
Call and apply call the function directly, while bind returns a new function (instead of calling the original function) that calls the original function with parameters specified by you
simulation
Var view = {element: ${'#div'), bindEvents: Function (){view.bindevevts (){function(){view.bindevevts (); This.element.onclick = function(){this.onclick () // how is this function called? OnClick: function(){}}Copy the code
When this element is clicked, this function should be called, it should be called by the browser, and the browser calls call. What is the first parameter of the browser call? Look at the document
The documentation tells me that the first argument to my call is the element that triggers the event
So the browser is callingfunction(){ this.onClick() }
And it will call, and the first argument that call gives us is the element that was clicked on, which is the pseudocode div above,this.onClick()
What if this is div? I can’t get this
// pseudo-code 2 // with this?? var view = { element: ${'#div'), var _this = this bindEvents: function(){ this.element.onclick = function(){ _this.onClick() // _this.onClick.call(_this) } }, onClick: Function (){}} var view = {element: ${'#div'), bindEvents: function(){ this.element.onclick = function(){ view.onClick() } }, onClick: function(){ } }Copy the code
The forgery of this is not recommended, so there is another way
Var view = {element: ${'#div'), bindEvents: Function (){this.element.onclick = this.onclick ().bind(this)}, onclick: function(){ this.element.addClass('active') } }Copy the code
You want to use onClick but you have to write a new function to call the onClick in the new function
Function (){this.onclick.call(this)} function(){this.onclick.call(this)}Copy the code
Bind’s job is to add a call to onClick when you call the new bind function
// bind this.onclick. bind = function(x, y, {this. OnClick return function(){oldFn. Call (x, y, z); }} this.element.onclick = this.onclick ().bind(this)Copy the code
When the user clicks on the div, the browser calls function(){oldFn. Call (x, y, z)}, which calls the previous function this.onClick followed by a call, whose argument is this
I saw a little dizzy = =, here I recommend a JavaScript in-depth bind implementation of Hu Yu
The following code is from Hu Yu's blog, the link is given at the top
var foo = {
value: 1
}
function bar() {
console.log(this.value);
}
// Returns a new function called bar.bind(foo) named bindFoo
var bindFoo = bar.bind(foo) // bar.bind(foo)()
// The new function calls the old function
bindFoo() // 1 is equivalent to bar.call(foo), which I specify
Copy the code
Use.bind to keep this unchanged
function f1(p1, p2){
console.log(this,p1,p2)
}
let f2 = f1.bind({name: 'hone'})
// f2 is the function that binds this to f1
f2() Call ({name: 'hone'})
Copy the code
.bind can also bind other parameters
let f3 = f1.bind({name: 'hone'}, 'hi')
f3() Call ({name: 'hone'}, 'hi')
Copy the code
The function is currified
What is corrification
Functions of x and y
G = f(x=1)(y) =1 + 2yCopy the code
G is called a Partial function of z. G is just a part of z
Corrification: to fix one of the parameters of a function, get a new function, reduce the number of functions, output a new function
🌰 example
// Before currization
function sum(x, y){
return x+y
}
// After currization
function addOne(y){
return sum(1, y)
}
addOne(4) / / 5
function addTwo(){
return sum(2, y)
}
addTwo(4) / / 6
Copy the code
So addOne is to fix the x of sum to 1 and then add the rest
Currization can be used to do lazy evaluation, where when you call my first function, I don’t really do anything, and when I call my last function, I do it
Recommend the article
- www.yinwang.org/blog-cn/201…
- zhuanlan.zhihu.com/p/31271179
Higher-order functions
know
In mathematics and computer science, a higher-order function is one that satisfies at least one of the following conditions:
- Accepts one or more functions as input:
forEach
sort
map
filter
reduce
- Output a function:
lodash.curry
- But it can also satisfy both conditions:
Function.prototype.bind
Function: can be arbitrary combination of functions
🌰 example
let sum = 0
let arr = [1.2.3.4.5.6]
for(let i = 0; i < arr.length; i++){
if(arr[i] % 2= = =0){
sum += array[i]
}
}
// The above code can be written as
arr.filter(n= > n % 2= = =0)
.reduce((sum, item) = > {return sum +item}, 0)
let arr1 = [1.4.6.2.3.8.7.9.5]
arr1.filter( n= > n % 2= = =1)
.sort((a, b) = > {return a-b},0)
Copy the code
Callback and constructor
The callback
Noun form: A function taken as an argument is a callback
Verb form: To invoke this callback
Callbacks and asynchrony have nothing to do with it
The figure shows a synchronous callback
SetTimeout (fn,1000) This is an asynchronous callback
The constructor
The function that returns an object is a constructor, usually capitalized
Arrow function
👉 🏻 link