最近又在重新复习js,不怎么用有些就就生疏了,每天都要复习复习在复习才行,分享一下跟着大神学习的日常笔记记录。
有些錯誤可能是沒寫對中英字符,可能會報錯,都手寫的,見諒,废话不多说半句,开始复习吧!
* 定义好了函数之后,javascript提供了3种调用函数的方式
1:直接调用函数:这种函数的调用时最常见,最普遍的方法。
对象.函数引用:
//当声明的一个函数没有指名分配给哪个对象使用的时候,默认分配给的是window对象.
栗子:
function aa(name,age){
alert("hello"+name+",今年:"+age)
}
window.aa("livia",18);
call方法调用函数:
函数引用.call(调用者,参数1,参数2,...)
栗子:
function aa(arr, func) {
func.call(window, arr);
}
aa([1, 2, 3], function(arr) {
for(i in arr) {
document.write(arr[i] + "<br/>")
}
})
2:以apply方法调用函数:
函数引用.apply(调用者,arguments)
//arguments相当于是数组,用来存放多个can'参数。和call调用方式类似
栗子:
function aa(arr, func) {
func.apply(window, arr);
}
aa([1, 2, 3], function([arr]) {
for(i in arr) {
document.write(arr[i] + "<br/>")
}
})
* 函数的返回值
javascriptzhon中的函数没声明返回类型,当函数想要返回值的时候,直接加上return“值”语句即可,假如不加就代表此函数没有任何返回值。
* 局部变量和局部函数
a: 根据变量的定义范围不同,变量有全局变量和局部变量之分,直接定义的变量是全局变量,在函数中定义的变量称为局部变量,局部变量只能在函数内有效,如果全局变量和局部变量使用相同的变量名,则局部变量将覆盖全局变量
b:与局部变量对应的是局部函数,局部函数在是函数中定义的,外部函数可以可以直接调用其内部的函数,在外部函数外直接调用内部函数是不可以的,所以只有当外部函数被调用时,内部局部函数才会被执行。
栗子:
1:
var name = "taolesi";
function func2() {
var age = 18;
alert(name)
}
func2();
}
func1();
//直接弹出taolesi
2:
function show(){
return function(){
alert("taolesi")
}
}
var func = show();
func();
//直接弹出taolesi
3:闭包
function func3(){
var a =1;
function func4(){
alert(a);
}
return func4;
}
var func = func3();
func();
//直接弹出1
来一波大神总结的闭包吧~~~
* 閉包(Closure)
閉包是函式記得並存取語彙範疇的能力,可說是指向特定範疇的參考,因此當函式是在其宣告的語彙範疇之外執行時也能正常運作。
範例如下。
function foo() {
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var baz = foo();
baz(); // 2
說明
- 函式能夠存取的範疇即是其被內嵌後往外推的範圍,例如 bar 被內嵌於 foo 之內,因此 bar 內變數可存取的範圍就是 foo 和全域範疇。因此,基於語彙範疇的變數查找規則,bar 內的 a 在自己的函式範疇內找不到定義的話,可往外層的範疇查找,於是在 foo 內找到了,得到 a 為 2。其中,console.log(a) 是執行 RHS 查找。
- JavaScript 引擎的垃圾回收機制會釋放不再使用的記憶體,但閉包為了保留函式記得和存取其語彙範疇的能力,就會予以保留,不做記憶體回收。因此,bar 仍保留指向 foo 的內層範疇的參考,這個參考就是閉包。
- 最後,雖然 baz 位於 bar 所定義的範疇之外,但由於閉包的緣故,bar 仍能正常執行,而得到 a 的值。
* 迴圈與閉包
如果今天要實作一個每秒依序印出數字 1, 2, 3, ..., 5 的功能,你會怎麼做呢?
是這樣嗎?
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000 );
}
這的確是錯誤的。由於 console.log(i) 中的 i 會存取的範疇是 for 所在的範疇(目前看起來是全域範疇,因為 var 宣告的變數不具區塊範疇的特性),因此當 1 秒、2 秒...5 秒後執行 console.log(i) 時,就會去取 i 的值,而此時 for 迴圈已跑完,i 變成 6,因此就會每隔一秒印出一個「6」。
若希望每隔一秒印出 1、2、...5,可使用 IIFE 加入新的範疇來修改,意即為每次迭代都建立一個新的函式範疇(但其實我們想要的是建立一個區塊範疇)。
-
for (var i = 1; i <= 5; i++) { (function(j) { setTimeout(function timer() { console.log(j); }, j * 1000); })(i); }
结果如下:
既然是要為每次迭代建立區塊範疇,更好的解法就是使用 let,let 會在每次迭代時重新宣告變數 i,並將上一次迭代的結果作為這一次的初始值。
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}//依次输出12345
结果如下: