閉包
概念:當(dāng)內(nèi)部函數(shù)被保存到外部時(shí),將會(huì)生成閉包。閉包會(huì)導(dǎo)致原有作用域鏈
舉例分析:
function a(){
function b(){
var bbb = 234;
console.log(aaa);
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
//a函數(shù)在執(zhí)行的時(shí)候,會(huì)生成自己的執(zhí)行期上下文AO對(duì)象,b函數(shù)是在
//a函數(shù)內(nèi)部定義的,所以b函數(shù)在定義的時(shí)候,形成的執(zhí)行期上下文隊(duì)像
//就會(huì)有a函數(shù)的AO對(duì)象,當(dāng)a函數(shù)執(zhí)行完畢的時(shí)候,內(nèi)部的變量會(huì)被當(dāng)作垃圾
//回收,此時(shí)a函數(shù)的執(zhí)行期上下文被銷毀,但a產(chǎn)生的AO對(duì)像并沒(méi)有被當(dāng)作垃圾回收,
//因?yàn)榇藭r(shí)b函數(shù)被保存出來(lái),然后javascript程序并沒(méi)有運(yùn)行完畢,
//b函數(shù)依然指向a函數(shù)的AO對(duì)象,b執(zhí)行的時(shí)候依然可以從a函數(shù)內(nèi)部拿值
閉包的應(yīng)用:
//1,實(shí)現(xiàn)累加器
function add(){
var num = 100;
function b (){
num++;
console.log(num);
}
return b;
}
var counter = add();
counter();//101
counter();//102
//b函數(shù)每次都是拿的add函數(shù)所產(chǎn)生的那個(gè)AO對(duì)象,所以每次都會(huì)加一
//2,可以做緩存
function eater(){
var food = "";
var obj = {
eat:function (){
console.log('i am eating'+food);
food = "";
},
push:function (myFood){
food = myFood;
}
}
return obj;
}
var eater1 = eater();
eater1.push('banana');
eate1r.eat();
//3,私有化變量
function Father(surname,address){
var money = 10000;
this.xing = surname;
this.address = address;
this.howmuchmony = function (){
console.log("我有多少錢:",money);
}
}
var son = new Father("sun","杭州");
son.money;//訪問(wèn)不到
son.howmuchmony();//只有son提供了相應(yīng)的方法,你才能訪問(wèn)到
立即執(zhí)行函數(shù)
概念:執(zhí)行完立即被銷毀的函數(shù),javascript提供給我們的唯一可以執(zhí)行完手動(dòng)銷毀函數(shù)的方式。
實(shí)則是被當(dāng)作表達(dá)式被括號(hào)執(zhí)行了。此類函數(shù)沒(méi)有聲明,在一次執(zhí)行過(guò)后即釋放。適合做初始化工作。
假設(shè)全局有兩個(gè)函數(shù)a和b,這兩個(gè)函數(shù)除非等到j(luò)avascript執(zhí)行完,不然一直占用內(nèi)存空間得不到釋放。
形式1:( function () {}() );//w3c建議第一種
形式2:( function () {})();
其他的一些寫法:
function test(){
var a = 123;
}();
//這種形式不能執(zhí)行,這種叫函數(shù)聲明,只有表達(dá)式才能被執(zhí)行符號(hào)執(zhí)行
var test = function (){
console.log(5464);
}();
+ function test1(){
console.log(8788);
}();
- function test2(){
console.log(8788);
}();
! function test3(){
console.log(8788);
}();
(function test() {
console.log(89);
}());
//+,-,!會(huì)把函數(shù)聲明變成表達(dá)式,所以能被執(zhí)行,能被執(zhí)行符號(hào)執(zhí)行的表達(dá)式會(huì)自動(dòng)忽略函數(shù)名,
//此時(shí)test(),是undefined,這種寫就相當(dāng)于立即執(zhí)行函數(shù),執(zhí)行完被釋放,test寫了也沒(méi)意義。
下面看些題目
一、
function test4(a,b,c,d){
console.log(a+b+c+d);
}();//這樣程序會(huì)報(bào)錯(cuò)
function test4(a,b,c,d){
console.log(a+b+c+d);
}(1,2,3,4);
//理論上不能執(zhí)行,這樣不會(huì)報(bào)錯(cuò),也不會(huì)執(zhí)行函數(shù),程序可以照常運(yùn)行
//因?yàn)?)如果當(dāng)成執(zhí)行符號(hào)就會(huì)報(bào)錯(cuò),系統(tǒng)是能不報(bào)錯(cuò)就不報(bào)錯(cuò),就會(huì)解釋成
// function test4(a,b,c,d){
// console.log(a+b+c+d);
// }
// (1,2,3,4);這樣的兩段代碼
//把(1,2,3,4);解釋成都好表達(dá)式
//test()還是可以運(yùn)行
二、
function test5(){
var arr = [];
for(var i=0;i<10;i++){
( function(j){
arr[j] = function (){
console.log(j);
}
}(i))//立即執(zhí)行函數(shù)里面有函數(shù)被返回,也是可以訪問(wèn)里面的變量,閉包的應(yīng)用
}
return arr;
}
var myArr = test5();
for(var i=0;i<myArr.length;i++){
myArr[i]();//每次去訪問(wèn)i的時(shí)候,都是去不同的AO對(duì)象里面去找
}
三、
使用原生js,addEventListener,給每個(gè)li元素綁定一個(gè)click事件,輸出他們的順序
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
function foo(){
var liCollection = document.getElementsByTagName("li");
for(var i=0;i<liCollection.length;i++){
(function(j){
liCollection[j].addEventListener("click",function(){
console.log(j);
})
}(i))
}
}
foo();
四、
寫一個(gè)方法,求一個(gè)字符串的字節(jié)長(zhǎng)度。(提示:字符串有一個(gè)方法charCodeAt();一個(gè)中文占兩個(gè)字節(jié),一個(gè)英文占一個(gè)字節(jié))
charCodeAt()方法可返回指定位置的字符串Unicode編碼。這個(gè)返回值是0-65535
之間的整數(shù)。當(dāng)返回值是<=255時(shí)為英文,當(dāng)返回值>255時(shí)為中文
// function retBytesLen(str){
// var count = 0;
// for(var i=0;i<str.length;i++){
// if(str.charCodeAt(i)<=255){
// count++;
// }else{
// count+=2;
// }
// }
// return count;
// }
function retBytesLen(str){
var len = str.length;
var count = len;
for(var i=0;i<len;i++){
if(str.charCodeAt(i)>255){
count++;
}
}
return count;
}
五、
var f = (
function f(){
return "1";
},
function g(){
return 2;
}
)();
console.log(typeof f) //number
// var f = (
// function g(){
// return 2;
// }
// )();簡(jiǎn)化候就是立即執(zhí)行函數(shù)
六、
var x = 1;
if(function f(){}){
x+=typeof f;
}
console.log(x);
//括號(hào)會(huì)把函數(shù)變成表達(dá)式,變成表達(dá)式他就不是函數(shù)定義,就消失了
//沒(méi)定義的變量只有放在typeof 里面才不會(huì)報(bào)錯(cuò),返回undefined,
//typeof 返回字符串類型,
七、
function Person(name,age,sex){
var a = 0;
this.name = name;
this.age = age;
this.sex = sex;
function sss(){
a++;
console.log(a);
}
this.say = sss;
}
var person1 = new Person();
person1.say();//1
person1.say();//2
var person2 = new Person();
person2.say();//1