作用域
對象 | 類型 |
---|---|
window | 全局作用域 |
function | 局部作用域(函數(shù)作用域) |
{ } | 塊狀作用域 |
this | 動態(tài)作用域 |
全局作用域
全局作用域: 變量在函數(shù)外部或者花括號外部定義的變量烤咧,即擁有全局作用域(不討論 沒用var在函數(shù)內(nèi)部聲明的變量)
//在全局作用域下用var定義abc
var abc = 123 ;
//在全局作用域中可以調(diào)用該變量
function test(){
console.log(abc);
//在函數(shù)內(nèi)部(函數(shù)作用域)也可調(diào)用abc變量
}
test(); //控制臺輸出123
//第二種情況在函數(shù)內(nèi)部 沒用var定義的變量
function test(){
abc=123;
console.log(abc); //輸出123
//在函數(shù)內(nèi)部可以調(diào)用
}
test(); //輸出123
console.log(abc); //輸出123
//在全局作用域中可以訪問
特別注意
用var在全局作用域中的定義的變量 和在函數(shù)內(nèi)部沒用var聲明的變量有本質(zhì)的區(qū)別詳見下述代碼塊
var abc = 123;
function test(){
abcd = 321;
}
test();
console.log(abc); //輸出123
console.log(abcd); //輸出321
delete abc;
delete abcd;
console.log(abc); //輸出123
console.log(abcd); //提示: abcd is not defined
//沒有用var聲明的變量相當(dāng)于是window下的一個屬性,
//可以用delete刪除,而用var定義的變量不能被delete刪除旬陡。
//所以abc可以訪問到,abcd會報錯 提示abcd沒有定義
局部作用域(函數(shù)作用域)
局部作用域: 變量在函數(shù)內(nèi)部部或者花括號內(nèi)部部定義的變量宠哄,即擁有局部作用域。從外層作用域是無法訪問的 是一個封閉的作用域
function test(){
var abc = 123;
}
console.log(abc); //報錯abc未定義
//由于abc在函數(shù)內(nèi)部定義定義的 即在函數(shù)作用域下起作用所以在外層作用域中使用該變量時贪薪,
//報錯提示未定義
若在需要訪問內(nèi)部變量的場景下有兩種方法可以使用
第一種 用閉包返回
function test(){
var abc = 123;
function test123(){
return abc
}
return test123
}
console.log(test()()); // 輸出123 這就通過閉包的方式在全局作用域下,
//訪問到在test函數(shù)中定義的abc變量了
第二種 直接return
function test(){
var abc = 123;
return abc
}
console.log(test()); //輸出123
return是函數(shù)對外交流的窗口
ES6塊狀作用域 { }
//用var聲明的變量除了函數(shù)作用域的{ } 其余的{}定義的變量都不是局部作用域
if(true){
var abc = 1;
console.log(abc); // 輸出1
}
console.log(abc); //輸出1
//用let聲明的變量在{ }中就形成塊狀作用域 只在{}中可以訪問到
if(true){
let abc = 1;
console.log(abc); //輸出1
}
console.log(abc); //報錯 abc未定義
動態(tài)作用域 (this)
可以用call bind apply 動態(tài)的指定this的指向
window.a = 1;
function test() {
console.log(this.a)
}
test.bind({a:100})() //輸出100 用bind改變了this的指向 {a:100}
test() // 輸出1 此時的this指向window
區(qū)分靜態(tài)作用域和動態(tài)作用域
//在全局中定義一個函數(shù)test
function test(){
console.log(abc)
}
// 在全局中定義另一個函數(shù)test1
function test1(){
//在局部中定義變量
var abc = 123;
//調(diào)用全局中定義的函數(shù)
test();
}
var abc = 321;
test1(); //輸出321
上述代碼,調(diào)用test1()輸出321說明在test()執(zhí)行的時候找的abc是全局下的abc,也就是test函數(shù)定義的時候所在作用域下的abc嘉蕾。 此時的作用域是全局作用域,是在定義的時候決定的 這就稱之為靜態(tài)作用域霜旧。
而javascript默認(rèn)使用靜態(tài)作用域
若上述代碼采用動態(tài)作用域的話 test1的輸出則為123,執(zhí)行過程就是test執(zhí)行的時候本身沒有abc變量 直接往執(zhí)行地的上層作用域?qū)ふ?在test1作用域中找到變量abc值為123 則test1最后結(jié)果就為123.
let && const
let
1错忱、用let聲明的變量具有塊級作用域
//形成了一個代碼塊 外部訪問不到變量abc
{
let abc = 1
}
console.log(abc); //報錯
2、用let聲明的全局變量不是全局對象window的屬性
就是不能通過window來訪問
var abc = 1
console.log(window.abc) //輸出1 可以用window來訪問
-----------------------
let abc = 1
console.log(window.abc) // 顯示未定義
3挂据、用let重定義變量會拋出一個語法錯誤
即用let的定義的變量不能再重新定義
var a = 1;
var a = 2 ;
console.log(a) // 輸出為2
---------------------------
let a = 1;
let a = 2 ;
console.log(a) // 報錯提示a已經(jīng)被定義過
4以清、let聲明的變量不會進行變量提升
console.log(a); //由于變量提升此時已經(jīng)被賦值為undefined
var a = 1 ;
console.log(a); //報錯由于用let聲明的變量沒有變量提升 所以此時還找不到變量a
let a = 1 ;
Const
首先用Const定義的變量都具有l(wèi)et的特性 其次const定義的變量還不能被更改,即定義的是一個常量
const abc = 123;
abc = 12;
console.log(abc);//報錯常量變量被賦值 Assignment to constant variable.
數(shù)組遍歷
首當(dāng)其沖的就是for循環(huán)
const arr = [1,2,3,4,5]
for(let i = 0;i<arr.length;i++){
console.log(i+':'+arr[i])
//輸出索引 以及對應(yīng)的值
}
for循環(huán)支持contiune 和break 可以讓數(shù)組遍歷停止
const arr = [1,2,3,4,5]
for(let i = 0;i<arr.length;i++){
if(i === 3){
continue
}else{
console.log(i+':'+arr[i])
//跳過索引為3的那項 繼續(xù)遍歷到結(jié)束
}
}
-------------------------------
const arr = [1,2,3,4,5]
for(let i = 0;i<arr.length;i++){
if(i === 3){
break
}else{
console.log(i+':'+arr[i])
//遇到索引為3的項 直接結(jié)束遍歷
}
}
forEach
不支持continue 和break
const arr = [1,2,3,4,5]
arr.forEach(function(item){
console.log(item) //不需要索引直接輸出每一項的值
})
every
可以用return true 和return false(默認(rèn)是設(shè)置為return false)來控制數(shù)組遍歷的過程
const arr = [1,2,3,4,5]
arr.every(function(item){
console.log(item)
//只會輸出1 由于默認(rèn)設(shè)置為return false
})
----------------------------
const arr = [1,2,3,4,5]
arr.every(function(item){
console.log(item)
return true
// 由于設(shè)置為return true 則會輸出數(shù)組中的每一項
})
模擬for循環(huán)的contiune 和 break
const arr = [1,2,3,4,5]
arr.every(function(item){
if( item === 2){
}else{
console.log(item)
}
return true
// 跳過了item === 2 的情況 相當(dāng)于continue
})
--------------------------------
const arr = [1,2,3,4,5]
arr.every(function(item){
if( item === 4){
return false
}else{
console.log(item)
}
return true
// 遇到過了item === 4 的情況直接退出循環(huán)
})
for ...in (是為對象設(shè)計api 不適用于數(shù)組)
支持 continue 和 break
const arr= [1,2,3,4,5]
arr.a = 123
for(key in arr){
console.log(key)
} // 輸出 0,1,2纬朝,3,4勒葱,5,a 并不適用于數(shù)組
//而且上述代碼的key是為字符串
for...of (可以遍歷對象和數(shù)組以及不是數(shù)組也不是對象的自定義的數(shù)據(jù)結(jié)構(gòu) 可以自定義遍歷的方式)
支持 break continue return
const arr= [1,2,3,4,5]
for(item of arr){
console.log(item)
}
---------------------
const arr= [1,2,3,4,5]
for(item of arr){
if( item === 3){
break
}else{
console.log(item) //輸出1,2 遇到3就直接退出循環(huán)
}
}
----------------------
const arr= [1,2,3,4,5]
for(item of arr){
if( item === 3){
continue
}else{
console.log(item) //輸出1障贸,2错森,4,5跳過值為3的項
}
}
自定義結(jié)構(gòu)后面補充
偽數(shù)組
函數(shù)中的arguments 篮洁、DOM中的NodeList等涩维。將偽數(shù)組轉(zhuǎn)換成數(shù)組讓其可以使用數(shù)組的方法
偽數(shù)組特點 1、按索引方式存儲數(shù)據(jù)(或者數(shù)據(jù)存儲為空) 2袁波、具有l(wèi)ength屬性 如下代碼
const arrLike = {
0:"a",
1:"b",
2:"c",
length:3
}
function test(num1,num2,num3,num4,num5,num6){
let args = [].slice.call(arguments);
//let args = Array.prototype.slice.call(arguments); 調(diào)用數(shù)組對象上的slice并給arguments使用
//用call將數(shù)組的api用在新的對象上
console.log(args)
}
test(1,2,3,4,5,6); //args 顯示為數(shù)組類型
DOM中的NodeList同上所述
Array.from()
再ES6中可以直接用Array.from() 將偽數(shù)組轉(zhuǎn)換為數(shù)組
Array.from() 也可以用于初始化數(shù)組
function test(num1,num2,num3,num4,num5,num6){
let args = Array.from(arguments)
console.log(args)
}
test(1,2,3,4,5,6); //args 顯示為數(shù)組類型
語法:Array.from(arrayLike,mapFn,thisArg)
參數(shù) | 含義 |
---|---|
arrayLike | 必須參數(shù)瓦阐,偽數(shù)組 |
mapFn | 可選參數(shù),轉(zhuǎn)換后的數(shù)組中的每個元素會執(zhí)行該回調(diào)函數(shù) |
thisArg | 可選參數(shù)篷牌,執(zhí)行回調(diào)函數(shù)后mapFn時this對象 |
function test(num1,num2,num3,num4,num5,num6){
let args = Array.from(arguments,(item)=>{ return item*2})
console.log(args)
}
test(1,2,3,4,5,6); //args 顯示為數(shù)組類型 并且每項值都乘2
用Array.from()初始化
ES5方法
let arr = Array(6).join(' ').split('').map(function(){return 1})
console.log(arr);
--------------------------------
ES6
let arr = Array.from({length:5},function(){ return 1});
//這里的偽數(shù)組前面的數(shù)據(jù)為空
console.log(arr);
Array.of
let array = Array(5) //生成長度為5的數(shù)組
let array = Array(5,6,7) //生成[5,6,7]
let array = [] //字面量創(chuàng)建數(shù)組
----------------------------
let array = Array.of(1,2,3,4,5); //生成[1,2,3,4,5]
let array = Array.of(1); //生成[1] 要區(qū)別于Array(1)
參數(shù) | 含義 |
---|---|
elementN | (必選參數(shù)) 任意個參數(shù)睡蟋,將按順序成為返回數(shù)組中的元素 |
Array.fill
用一個固定值填充一個數(shù)組中從起始索引到終止索引內(nèi)的全部元素。不包括終止索引
//初始化數(shù)組
let array = Array(5).fill(8);
//在只有一個參數(shù)的情況下 后面兩個參數(shù)的默認(rèn)值為0和length
console.log(array); //打印一個長度為5各項值為8的數(shù)組 [8,8,8,8,8]
---------------------------
let arr = [1,2,3,4]
arr.fill(0,1,2) //打印[1,0,3,4]
//fill有三個參數(shù) 第一個為需要添加的值 第二個為起始位置,第三個是終止索引但替換的時候不包括該索引值
//
參數(shù) | 含義 |
---|---|
value | (必填參數(shù)) 用來填充數(shù)組元素的值 |
start | (可選參數(shù))起始索引枷颊,默認(rèn)值為0 |
end | (可選參數(shù)) 終止索引戳杀,默認(rèn)值為this.length |
查找數(shù)組中的元素
ES5中用filter (將數(shù)組中所有的符合條件的元素都放在一個數(shù)組里返回)
let arr = [1,2,3,4,5]
let find = arr.filter(function(item){
return item === 5
})
console.log(find) //返回 數(shù)組[5] 若沒有返回空數(shù)組
--------------------------------
ES6中的find(將數(shù)組中第一個的符合條件的元素返回 關(guān)注的側(cè)重點不同)
let arr = [1,2,3,4,5]
let find = arr.find(function(item){
return item > 2
})
console.log(find) //返回3
-----------------------------
ES6中的findIndex(將數(shù)組中第一個的符合條件的元素的索引值返回)
let arr = [1,2,3,4,5]
let find = arr.findIndex(function(item){
return item > 2
})
console.log(find) //返回2