Home > Web Front-end > JS Tutorial > body text

JavaScript Basics (6) Function Expression Closure_Javascript Skills

WBOY
Release: 2016-05-16 15:26:22
Original
974 people have browsed it

In fact, the main reason why js supports function closures is because js needs functions to be able to save data. The saved data here is that only the values ​​of variables within the function will be saved after the function ends. As for why js needs to be able to save data within a function, that is that js is a functional language. Saving data within functions is a hallmark of functional languages.

Review the three methods of defining functions introduced earlier

functiosu(numnumreturnunum//Function declaration syntax definition
vasufunction(numnum)returnunum}//Function expression definition
vasuneFunction("num""num""returnunum")//Functio constructor

Before analyzing closures, let’s take a look at common mistakes in defining and calling functions.

Example 1:

sayHi(); //错误:函数还不存在
var sayHi = function () {
  alert("test");
};
Copy after login

Example 2:

if (true) {
  function sayHi() {
    alert("1");
  }
} else {
  function sayHi() {
    alert("2");
  }
}
sayHi();//打印结果并不是我们想要的
Copy after login

Example 3:

var fun1 = function fun2() {
  alert("test");
}
fun2();//错误:函数还不存在
Copy after login

In Example 1, we cannot call the function before defining it using function declarative syntax. Solution:

1. If you use a function expression to define a function, it needs to be called after the expression is defined.

var sayHi = function () {
  alert("test");
};
sayHi()
Copy after login

2. Use function declarations. (Here the browser engine will promote function declarations and read the function declaration before all code is executed)

sayHi(); 
function sayHi () {
  alert("test");
};
Copy after login

In Example 2, our expected result should be to print 1, but the actual result is to print 2.

if (true) {
  function sayHi() {
   alert("1");
  }
  } else {
  function sayHi() {
   alert("2");
  }
}
sayHi();//打印结果并不是我们想要的
Copy after login

Why is this happening? Because of function declaration promotion, the browser will not judge the if condition during pre-parsing, and directly overwrites the first one when parsing the second function definition.

Solution:

var sayHi;
if (true) {
  sayHi = function () {
   alert("1");
  }
  } else {
  sayHi = function () {
   alert("2");
  }
}
sayHi();
Copy after login

In Example 3, we found that we can only use fun1() to call, but not fun2().

From my own understanding, I don’t know the real reason. No information found.

Because 1: function fun3() { }; is equivalent to var fun3 = function fun3() { }; as shown in the figure:

So you can only use fun1() to call, but not fun2().

Actually, I still have questions here? If anyone knows, please let me know.

Since fun2 cannot be called from outside, why can it be called from inside the function? Although I still can't get fun1 in the debugger.

Okay, let’s warm up with the three questions above. Let’s continue with today’s topic of “closures”.

1. What is closure?

Definition: It is a function that has access to variables in the scope of another function

Let’s start with an example function:

Example 1:

function fun() {
  var a = "张三";
}
fun();//在我们执行完后,变量a就被标记为销毁了
Copy after login

Example 2:

function fun() {
  var a = "张三";
  return function () {
    alert("test");
  }
}
var f = fun();//同样,在我们执行完后,变量a就被标记为销毁了
Copy after login

Example 3:

function fun() {
  var a = "张三";
  return function () {
    alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】
//这就是闭包,当函数A 返回的函数B 里面使用到了函数A的变量,那么函数B就使用了闭包。
示例:
function fun() {
  var a = "张三";
  return function () {
   alert(a);
  }
}
var f = fun();//【现在情况发生变化了,如果a被销毁,显然f被调用的话就不能访问到变量a的值了】
f();//【然后变量a的值正常的被访问到了】
Copy after login

Obviously, misuse of closures will increase memory usage. So try not to use closures unless there are special circumstances. If used, remember to manually set a null reference so that the memory can be recycled f = null ;

Illustration: (Students who don’t understand scope chain, please read the previous article Scope and Scope Chain first)

2. What is an anonymous function? (Just explaining the concept)

For example: (that is, a function without a name)

About the weird phenomenon of this when the return value of the function in the object is an anonymous function

Before explaining, please clear your head first and don’t get more confused as you read. If you are confused, just ignore the following.

var name1 = "张三";
var obj = {
  name1: "李四",      
  fun2: function () {
    alert(this.name1);
  },
  fun3: function () {
    return function () {
      alert(this.name1);
    }
  }
}
Copy after login

obj.fun2();//The printing result "李思" is as expected.
obj.fun3()();//Because what is returned here is a function, we need to add a pair of () to call it. The printed result is "Zhang San", which is unexpected.
//It’s really confusing. What does this point to the overall situation?
We said before that "whichever object clicks the method, this is the object", then our obj.fun3()() prints "Zhang San", which means this executes the global scope.

We may understand why by looking at the example below.

var name1 = "张三";
var obj = {
  name1: "李四",      
  fun2: function () {
    alert(this.name1);
  },
  fun3: function () {
    return function () {
      alert(this.name1);
    }
  }
}    
//obj.fun3()();
var obj2 = {};
obj2.name1 = "test";
obj2.fun = obj.fun3();
obj2.fun();//打印结果"test",再次证明了“哪个对象点出来的方法,this就是哪个对象”.
var name1 = "张三";
var obj = {
  name1: "李四",
  fun2: function () {
   alert(this.name1);
  },
  fun3: function () {
    return function () {
     alert(this.name1);
    }
  }
}
//obj.fun3()();
var obj2 = {};
obj2.name1 = "test";
obj2.fun = obj.fun3();
obj2.fun();//打印结果"test",再次证明了“哪个对象点出来的方法,this就是哪个对象”.
Copy after login

我們來分解下 obj.fun3()() 先是  obj.fun3() 回傳一個匿名函數到了window作用域,然後接著呼叫this就指向了window了。 ( 感覺解釋有點勉強,也不知道對不,暫時自己先是這麼理解的 )

閉包形成的原因:記憶體釋放問題

一般,當函數執行完畢後,局部活動物件會被銷毀,記憶體中僅保存全域作用域,但閉包的情況是不一樣的。

閉包的活動物件依然會保存在記憶體中,於是像上例中,函數呼叫返回後,變數i是屬於活動物件裡面的,就是說其棧區還沒釋放,但你呼叫c()的時候i變數保存的作用域鏈從b()->a()->全域去尋找作用域var i宣告所在,然後找到了var i=1;然後在閉包內++i;結果,最後輸出的值就是2了;

以上所述是小編給大家分享的JavaScript基礎篇(6)之函數表達式閉包,希望大家喜歡。

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template