做用域是相對於變量而言的, 其意義就在與查找變量(肯定變量的來處, 變量是否能夠訪問到, 肯定變量在當前位置是否能夠取到值)javascript
JS
分函數做用域和全局做用域JS
變量又遵循就近使用的原則
xxx變量 is not defined
如何肯定函數做用域的上一級做用域java
函數的上一次做用域取決於函數聲明時的位置,而不是函數調用時的位置。數組
函數就聲明在全局做用域內閉包
<script> function fn(callback){ var age=18; callback() } fn(function(){ console.log(age); //age is not defined //分析:age變量: //一、查找當前做用域:並無 //二、查找上一級做用域:全局做用域 (此時函數就聲明在全局做用域內) //三、此時age變量就獲取不到fn函數內部的age變量 //看上一級做用域,不是看函數在哪裏調用,而是看函數在哪裏編寫,函數聲明在全局,它的上一級做用域就是全局做用域。 //-->由於這種特別,咱們一般會把做用域說成是:詞法做用域 }) </script>
函數聲明在其它的函數內 (閉包就是個典型案例)app
<script> function fn(){ var a=5; return function(){ a++; console.log(a); //a變量確定是能夠訪問的 } } var f1=fn(); //f1指向匿名函數 f1(); //6 f1(); //7 f1(); //8 //分析:a變量: //一、查找當前做用域:並無 //二、查找上一級做用域:fn函數做用域 (此時函數就聲明在fn函數內) //-->通常認爲函數執行完畢,變量就會釋放,可是此時因爲js引擎發現匿名函數要使用a變量,因此a變量並不能獲得釋放,而是把a變量放在匿名函數能夠訪問到的地方去了 //-->a變量存在於f1函數能夠訪問到的地方,固然此時a變量只能被f1函數訪問 </script>
函數的4種調用方式函數
普通函數調用的方式this
<script> var age = 18; //該age聲明在全局做用域下,其就會被掛載到window對象上,即window.age=18 var p = { age: 15, say: function () { console.log(this.age); //this指向window } } var s1 = p.say //s1 = function () {console.log(this.age);} s1(); //函數調用, 結果爲 18 </script>
方法的調用code
<script> var age = 18; //該age聲明在全局做用域下,其就會被掛載到window對象上,即window.age=18 var p = { age: 15, say: function () { console.log(this.age); //this指向p對象 } } p.say() //結果爲15 //p.say獲取的就是p對象內部的say方法,而後方法後+()就是方法的調用。 </script>
new調用(構造函數)對象
<script> var age = 18; var p = { age: 15, say: function () { console.log(this.age); //此時this指向構造函數new出來的實例,而實例中並無初始化age屬性 } } new p.say() //構造函數調用, 結果爲undefined </script>
<script> var age = 18; var p = { age: 15, say: function (age) { this.age = age console.log(this.age); } } new p.say(22) //構造函數調用, 結果爲22 </script>
上下文方式(call、apply、bind)ip
<script> var length = 21; //window.length = 21 function f1() { console.log(this.length); } f1.call([1, 3, 5]) //結果爲3,此時this指向[1,3,5]數組 f1.apply(this) //結果爲21,此時this指向window f1.call(5) //undefinde , 此時this指向 Number,其沒有length屬性 f1.bind(this)() //結果爲21 //bind方法只改變函數f1內部this指向,而不會讓函數執行,想讓其執行,須要在後面手動調用+() </script>