Interview question scope and closure

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:
Insert picture description here
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)

Insert picture description here
Insert picture description here

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
    Insert picture description here
Closure
  • There are two kinds of manifestations for the special situation of the application
  • Function is passed as a parameter
  • The function is returned
    Insert picture description here
    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! ! ! !

Insert picture description here

this

  • As a normal function
  • Use call apply bind
  • Is called as an object method
  • Called in the class method
  • Called in arrow function
    Insert picture description here
    Insert picture description here
    Insert picture description here

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'))
 	 

Insert picture description here

<!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

Guess you like

Origin blog.csdn.net/WLIULIANBO/article/details/114945839