Scope and closure
- topic
- Knowledge points
- answer
topic
How to take the value of this in different application scenarios?
Classification: 1: When being called as a normal function, the object pointed to by this is the pointer of window this is generally understood as who calls and who this points to
For example:
a() here is equivalent to window.a();
function a(){
var user = "candy";
console.log(this,user); // undefined
console.log(this); // window
};
a();
Next example:
var o = {
user:"candy:,
fn:function(){
console.log(this.user); // candy
},
};
0.fn();
The fn here is called by the 0 object, so at this time this points to the object o
Example 3:
var o = {
a:1,
b:{
a:2,
fn:function(){
console.log(this.a); // 2
}
}
};
o.b.fn();
This example prints out 2, which means that
if there is this in a function, but the call contains multiple layers, then this points to only the calling object at the previous level.
Although there is no attribute a in object b, this This also points to the object b, because this will only point to its parent object, regardless of whether there is something this wants in this object.
Example 4: More special
var o = {
a:1,
b:{
a:2,
function(){
console.log(this,a); // undefined
console.log(this); // window
}
}
};
var j = o.b.fn;
j();
Here this points to the window, is it a bit confusing? In fact, it is because you did not understand a sentence, which is also very important.
this always points to the last of its object calls , also is to see when it is executed who invoked the example 4 Although the function fn is the object b referenced, but did not execute when the fn assigned to the variable j so The final point is window, which is different from example 3, which executes fn directly.
2: Use call, apply, bind, the object pointed to by this is the incoming object. The
bind() method is mainly to bind the function to an object,
bind() will create a function, and the value of the this object in the function body will be Bind to the value of the first parameter passed in bind(),
for example, fn.bind(obj), can actually be understood as obj.fn(), at this time, the this in the fn function body naturally points to obj
function fn1(a,b,c){
console.log('this',this);
console.log(a,b,c);
return 'this is fn1';
}
const fn2 = fn1.bind({
x:100},10,20,30);
const res = fn2();
console.log(res);
The printed result is:
3: When the method as an object is called, this returns the called object
4: In the class method
5: Called in the arrow function, referring to the superior scope of the arrow function
6: this in the constructor
function FU(){
this.user = "candy";
};
var a = new Fu();
console.log(a.user); // candy
Here is because the new keyword is used. The new keyword
is to create an object instance, pointing to the this of its constructor
But note that there is a special case
of ☝️ when the constructor and return meet-
if the return value is an object, then this points to the returned object, and if the return value is not an object, then this points to an instance of the function.
Handwritten bind function
Standard Polyfill on MDN
if (!Function.prototype.bind) {
Function.prototype.bind = function(oThis) {
if (typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function() {
},
fBound = function() {
// this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
return fToBind.apply(this instanceof fBound ? this : oThis,
// 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
aArgs.concat(Array.prototype.slice.call(arguments)));
};
// 维护原型关系
if (this.prototype) {
// Function.prototype doesn't have a prototype property
fNOP.prototype = this.prototype;
}
// 下行的代码使fBound.prototype是fNOP的实例,因此
// 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
fBound.prototype = new fNOP();
return fBound;
};
}
Application scenarios of closures in actual development, with examples
The practical application of closures is mainly used to encapsulate variables. That is, the variables are hidden from the outside to get and modify.
function isFirstLoad() {
var _list = []
return function (id) {
if (_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
// 使用
var firstLoad = isFirstLoad()
firstLoad(10) // true
firstLoad(10) // false
firstLoad(20) // true
Knowledge points
- Scope and free variables
- Closure
- this
Scope
- Global scope
- Function scope
- Block-level scope (new in ES6)
JavaScript scope
The scope is a collection of accessible variables.
JavaScript scope
In JavaScript, objects and functions are also variables.
In JavaScript, the scope is a collection of accessible variables, objects, and functions.
JavaScript function scope: The scope is modified within the function.
JavaScript local scope
Variables are declared in functions, and variables are of local scope.
Local variables: can only be accessed inside the function.
Examples:
// 此处不能调用 carName 变量
function myFunction() {
var carName = "Volvo";
// 函数内可调用 carName 变量
}
Because local variables only work within functions, different functions can use variables with the same name.
Local variables are created when the function starts to execute, and the local variables are automatically destroyed after the function is executed.
JavaScript global variables
Variables defined outside the function are global variables.
Global variables have a global scope: all scripts and functions in the web page can be used.
Examples:
var carName = " Volvo";
// 此处可调用 carName 变量
function myFunction() {
// 函数内可调用 carName 变量
}
If the variable is not declared in the function (the var keyword is not used), the variable is a global variable.
In the following example, carName is in the function, but it is a global variable.
Examples:
// 此处可调用 carName 变量
function myFunction() {
carName = "Volvo";
// 此处可调用 carName 变量
}
JavaScript variable life cycle
The JavaScript variable life cycle is initialized when it is declared.
Local variables are destroyed after the function is executed.
Global variables are destroyed after the page is closed.
Function parameters
Function parameters only work within the function and are local variables.
Global variables in HTML
In HTML, global variables are window objects: all data variables belong to window objects.
Examples:
//此处可使用 window.carName
function myFunction() {
carName = "Volvo";
}
Free variable
- A variable is not defined in the current scope, but is used
- Go to the upper level scope, look for one layer at a time, until you find it
- If the global scope is not found, the error xx is not defined will be reported
Closure
- There are two kinds of manifestations for the special situation of the application
- Function is passed as a parameter
- The function is returned
as the return value The function is returned as the return value
function create(){
const a = 100
return function (){
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100
Function is passed as a parameter
function print (fn){
const a = 200
fn()
}
const a = 100
function fn(){
console.olg(a)
}
print(fn) // 100
Therefore, the search of free variables is in the place where the function is defined, and it is searched in the upper scope, not in the place of execution! ! ! !
this
- As a normal function
- Use call apply bind
- Is called as an object method
- Called in the class method
- Called in arrow function
Application of closures in actual development
- Hide data
- For example, a simple cache tool
that hides data in closures, only provides API
function craeteCache(){
const data = {
} // 闭包中的数据,被隐藏,不被外界访问
return {
set:function (key,val){
data[key] = val
},
get:function (key){
return data[key]
}
}
}
const c = craeteCache()
c.set('a',100)
console.log(c.get('a'))
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>js 基础知识 演示</title>
</head>
<body>
<p>一段文字 1</p>
<p>一段文字 2</p>
<p>一段文字 3</p>
</body>
<script>
let a
// for(i=0; i<10;i++){
for(let i=0; i<10;i++){
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click',function(e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
</script>
</html >
summary
- Acting on and free variables
- Closures: two common ways & free variable search rules
- this