Every Function is an instance of type Function. A Function is an object. A Function name is a pointer to an object.
// A semicolon is required
let sum = (num1, num2) = > {
return num1 + num2;
};
// Semicolons are not needed
function sum (num1, num2) {
return num1 + num2;
}
Copy the code
Arrow function
Arrow functions, while concise, are not suitable for some scenarios. Arrow functions cannot use arguments, super, and new.target, and arrow functions do not contain the prototype attribute.
The function name
A function name is a pointer to a function. A function can have multiple names
function sum(num1, num2) {
return num1 + num2;
}
/ / 20
console.log(sum(10.10));
/ / 20
let anotherSum = sum;
console.log(anotherSum(10.10)); / / 20
Copy the code
The name attribute
function foo() {}
let bar = function() {};
let baz = () = > {};
// foo
console.log(foo.name);
// bar
console.log(bar.name);
// baz
console.log(baz.name);
//(empty string)
console.log((() = > {}).name);
// anonymous
console.log((new Function()).name);
function sum(num1, num2) {
return num1 + num2;
}
let anotherSum = sum;
// sum
console.log(anotherSum.name);
Copy the code
Using bind adds a prefix
function foo() {}
// bound foo
console.log(foo.bind(null).name);
let dog = {
years: 1.get age() {
return this.years;
},
set age(newAge) {
this.years = newAge; }}let propertyDescriptor = Object.getOwnPropertyDescriptor(dog, 'age');
console.log(propertyDescriptor.get.name); // get age
console.log(propertyDescriptor.set.name); // set age
Copy the code
parameter
Js defines the number of parameters, and the use of different parameters passed in the case, is not an error. Because the argument in JS is essentially an array. In the body of a non-arrow function, you can access each argument of the function using arguments, which is an array object of classes. Arguments to ECMAScript functions are written for convenience only, not necessarily
function sayHi() {
console.log("Hello " + arguments[0] + "," + arguments[1]);
}
Copy the code
In non-strict mode, arguments and arguments are bound to each other (but they don’t refer to the same block of memory, just synchronize), and changing arguments[0] changes the value of the first argument as well.
However, if no actual arguments are passed, change arguments[0] to sync.
Arguments to the arrow function
The arguments keyword is not available in arrow functions
There is no overload
There is no overloading of functions in js; the last one overwrites the previous one.
The default parameters
function makeKing(name = 'Henry') {
return `King ${name} VIII`;
}
Copy the code
If the argument is undefined, the default argument is used. Arguments does not synchronize with default arguments. If arguments are used as default arguments, arguments will not get the value of the default argument.
The default argument may not be a fixed value, or it may be the return value of a function
let ordinality = 0;
function getNumerals() {
return ordinality++;
}
// Use the return value of getNumerals as the default argument
function makeKing(name = 'Henry', numerals = getNumerals()) {
return `King ${name} ${numerals}`;
}
// The default argument for numerals. Incrementing after each call
console.log(makeKing());
Copy the code
Default parameter scope with temporary dead zone
The default arguments to functions, like let and const, have a temporary dead band. The default value of the latter parameter, which can be used as the default value.
function makeKing(name = 'Henry', numerals = name) {
return `King ${name} ${numerals}`;
}
Copy the code
However, the former parameter cannot be used as the default value. The specific reasons are as follows
function makeKing(name = 'Henry', numerals = 'VIII') {
return `King ${name} ${numerals}`;
}
// Is equivalent to
function makeKing(name, numerals) {
let name = name || 'Henry';
let numerals = numerals || 'VIII';
return `King ${name} ${numerals}`;
}
Copy the code
Extension and collection of parameters
If the function wants to take every item in the array as an argument. You can’t accept array arguments at the same time
If you do not use the extension operator, you can use Apply
let values = [1.2.3.4];
getSum.apply(null, values)
Copy the code
Or use extension operators
let values = [1.2.3.4]; getSum(... values);Copy the code
Arguments can collect arguments passed in using the extension operator
let values = [1.2.3.4]
function countArguments() {
console.log(arguments.length);
}
/ / 5
countArguments(-1. values);Copy the code
Extended operators that can be used on named and default parameters
function getProduct(a, b, c = 1) {
return a * b * c;
}
/ / 2
console.log(getProduct(... [1.2]));
/ / 6
console.log(getProduct(... [1.2.3]))
Copy the code
Collect parameters
The extension operator can also be used on function parameters, which become an array
function getSum(. values) {
/ / [1, 2, 3]
console.log(values)
}
console.log(getSum(1.2.3))
Copy the code
If the extension operator is used as an argument, it cannot have any arguments afterwards because its length is variable
/ / error
function getProduct(. values, lastValue) {}
/ / right
function getProduct(lastValue, ... values) {}
Copy the code
Declarations and expressions of functions
Function declarations and function expressions are treated differently by the JS engine.
Before any code is executed, js reads the function declaration and generates the function definition in the execution context. A function expression, on the other hand, must wait until the code executes to its line before generating the function definition in the execution context.
// Can be executed normally
console.log(sum(10.10));
function sum(num1, num2) {
return num1 + num2;
}
Copy the code
Function declarations are read and added to the execution context before any code is executed. This process is called function declaration promotion.
The JS engine performs a scan before executing the code, elevating the found function declaration to the top of the source tree.
// You can see it like this
console.log(sum(10.10));
function sum(num1, num2) {
return num1 + num2;
}
// Inside JS, because function declarations are promoted, it actually looks like this
function sum(num1, num2) {
return num1 + num2;
}
console.log(sum(10.10));
Copy the code
Function expressions do not have function declaration promotion
// An error will be reported. If the code does not execute to the defined line, then there is no function definition in the execution context
console.log(sum(10.10));
var sum = function(num1, num2) {
return num1 + num2;
};
Copy the code
Function as value
Functions can be arguments, they can be return values. Functions that return values can be external to the contents of the function.
Function of the internal
this
In standard functions, this is the context object that treats the function as a method call. The this object of a standard function is determined only when it is called, and this is undefined when it is not called.
window.color = 'red';
let o = {
color: 'blue'
};
function sayColor() {
// this refers to window
console.log(this.color);
}
sayColor(); // 'red'
o.sayColor = sayColor;
// This refers to the o object
o.sayColor(); // 'blue'
Copy the code
In the arrow function, this refers to the context in which the arrow function is defined (if so)
window.color = 'red';
let o = {
color: 'blue'
};
// This is always the window object
let sayColor = () = > console.log(this.color);
sayColor(); // 'red'
o.sayColor = sayColor;
o.sayColor(); // 'red'
Copy the code
In the arrow function, this refers to the context in which the arrow function is defined. If the context of the arrow function is inside the normal function, the context is not determined until the normal function call.
const bar = {
fn () {
const fn = () = > {
console.log(this)
}
fn()
}
}
/ / this is the bar
bar.fn()
const fn = bar.fn
/ / this is a window
fn()
Copy the code
const bar = {
fn: () = > {
// This is already defined in the definition
console.log(this)}}/ / this is a window
// This is defined when the fn function is defined
bar.fn()
Copy the code
caller
The function that calls the current function, arguments.callee.caller, also points to the same reference (but currently tests return undefined).
function a() {
b();
}
function b() {
// a
console.log(b.caller);
}
a();
Copy the code
arguments
Class array object. Contains all the arguments actually passed in when the function is called. Arguments. callee pointer to the function in question.
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num - 1); }}// Equivalent to avoid strong coupling with the factorial name
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1); }}Copy the code
new.target
Target returns undefined. If new is called, the constructor is returned
Properties and methods of a function
- Length, length returns the number of function parameters
- Prototype is where all instance methods of a reference type are stored, all instances shared
- Apply (), which specifies this. The first argument is the value of this that needs to be set. The second argument can be an array of arguments or arguments object
- Call (), which specifies this, the first argument, and apply, but the arguments to the function need to be passed in sequence, not arrays
- Bind (), which is used to specify this, also needs to be passed in. Unlike apply or call, which calls the function immediately, bind returns the wrapped function
- ValueOf () returns the function itself
Partial function
Bind, another common way to do this is to have a function that has some default arguments
function addArguments(arg1, arg2) {
return arg1 + arg2
}
// add has an initial parameter of 1
const add = addArguments.bind(null.1)
/ / 3
add(2)
// 3, the second argument is ignored
add(2.3)
Copy the code
Functional expression
The most important difference between function expressions and function declarations is promotion
// There is a problem with this code
if (toggle) {
function a () {
console.log(1)}}else {
function a () {
console.log(2)}}// In the JS engine, it actually looks like this
function a () {
console.log(1)}function a () {
console.log(2)}if (toggle) {
} else{}Copy the code
But if you are using functional expressions, it is safe to do so
let sayHi;
if (condition) {
sayHi = function() {
console.log("Hi!");
};
} else { 10
sayHi = function() {
console.log("Yo!");
};
}
Copy the code
recursive
A function calls itself, and if it recurses by function name, the function is strongly bound. You can use arguments.callee to get a reference to yourself. Using arguments.callee in strict mode will cause an error.
closure
Closures are functions that refer to variables in the scope of another function,
function createComparisonFunction(propertyName) {
return function(object1, object2) {
// another scoped variable is used
let value1 = object1[propertyName];
let value2 = object2[propertyName];
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0; }}; }Copy the code
If the createComparisonFunction inner function is returned, the propertyName variable can still be used because the inner function retains the scope of the createComparisonFunction.
The scope list for the internal anonymous function contains the AO for the anonymous function, as well as the AO for the external createComparisonFunction function, and the global VO. When createComparisonFunction returns an anonymous function, the variables in createComparisonFunction can still be accessed because the anonymous function contains the AO of createComparisonFunction. As a side effect, createComparisonFunction’s AO cannot be recycled. ♻ ️
——– split line ——-
The little Red Book of closures is not as detailed here as uncle Tom’s blog. Here is uncle Tom’s blog, which is very nice 💗💗💗💗
👍 👍 👍 👍 👍 👍 👍 blog: https://www.cnblogs.com/tomxu/archive/2012/01/18/2312463.html, if you want to see the content of the lean, can see my notes to “learn” a deep understanding of JavaScript: https://github.com/peoplesing1832/blog/issues/43
——– split line ——-
It is important to note that closures preserve the scope of other functions. Overusing closures can cause memory to run out, and sometimes you need to manually free memory
function foo () {
return function () {}}let bar = foo()
bar()
// Manually release memory
bar = null
Copy the code
this
Since the inner function is the this object that cannot access the outer function, this is the window
window.identity = 'The Window';
let object = {
identity: 'My Object'.getIdentityFunc() {
return function() { return this.identity; }; }};// window,
console.log(object.getIdentityFunc()());
Copy the code
But if you store the this of an external function in a variable, you can implement a closure to retrieve the external this
window.identity = 'The Window';
let object = {
identity: 'My Object'.getIdentityFunc() {
let that = this;
return function() {
returnthat.identity; }; }};console.log(object.getIdentityFunc()()); // 'My Object'
Copy the code
A memory leak
function assignHandler() {
let element = document.getElementById('someElement');
element.onclick = () = > console.log(element.id);
}
Copy the code
Event handlers that use the AO (active object) of assignHandler cause the Element variable to be unrecyclable. How do you avoid memory leaks
function assignHandler() {
let element = document.getElementById('someElement');
let id = element.id;
element.onclick = () = > console.log(id);
element = null;
}
Copy the code
The element. Id is stored in a variable, but the event handlers still use assignHandler’s AO. The Element variable cannot be reclaimed. Element must be set to NULL in order to touch references to it.
A function expression that is invoked immediately
Block-level scopes can be simulated using IIFE
// IIFE
(function () {
for (var i = 0; i < count; i++) {
console.log(i);
}
})();
console.log(i); // Throw an error
Copy the code
In ES6, let and const are block-level scoped variables that do not require IIFE