ECMAScript學習(一)
目錄
變數提升
var關鍵字定義變數會有變數提升的問題
//這裡a未定義,不報錯有列印結果undefined
console.log(a); // undefined
var a = 10;
//列印fn呼叫也存在變數提升
function fn() {
var a = 3;
console.log("fn().a="+a)
}
console.log(fn())//undefined
let定義變數
let定義變數的特點
1. 暫時性死區
在let宣告的前面訪問不到(暫時性死區)(必須宣告之後再使用)
console.log(a);//Uncaught ReferenceError: a is not defined
let a = 10;
2. 不可以重複宣告
let a = 10;
let a = 1;//Uncaught SyntaxError: Identifier 'a' has already been declared
3. 塊級作用域
(1)var域let宣告變數的作用域在for迴圈中不相同
for (var i = 0; i < 3; i++) {
console.log(i);//0,1,2
}
console.log(i);//3
//for本身是一個父的作用域,而for裡面是一個子的作用域
for (let i = 0; i < 3; i++) {
let i = 10;
console.log(i);//10 10 10
}
console.log(i);// Uncaught ReferenceError: i is not defined
(2)let在兩個大括號之間就是一個作用域
{
// let在兩個大括號之間就是一個作用域
let a = 10;
let b = 4;
console.log(a, b);//10,4
}
let在for迴圈中的使用
點選每一個li顯示列印結果
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
新增點選事件
var aLi = document.getElementsByTagName('li');
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = function() {
console.log(i);//點選任何li都會列印5
}
}
上面點選任何li都會列印5,因為for迴圈一次性執行到5了。
解決方案一:
採用自定義屬性,給每一個li新增index屬性
for (var i = 0; i < aLi.length; i++) {
aLi[i].index = i;
aLi[i].onclick = function() {
console.log(this.index);//點選列印相應的索引值
}
}
解決方案二:
閉包實現變數的快取
for (var i = 0; i < aLi.length; i++) {
aLi[i].onclick = (function(i) {
return function() {//閉包
console.log(i);
}
})(i);
}
解決方案三:
let宣告塊級作用域
for (let i = 0; i < aLi.length; i++) {
aLi[i].onclick = function() {
console.log(i);
}
}
const宣告變數
1用於宣告常量:
一經宣告,後面不再修改的變數
const userName = '張三';
userName = '李四';
//Uncaught TypeError: Assignment to constant variable.
2宣告引用型別
宣告引用型別變數,只要不更改地址,改屬性是允許的。
下面修改地址,報錯:分配給常量變數
const obj = { a: 1 };
obj = {a: 10}//Uncaught TypeError: Assignment to constant variable.
修改屬性是沒問題的
const obj = { a: 1 };
obj.a = 10;
console.log(obj.a);//10
3 宣告賦值
宣告時,必須賦值否則報錯。
//Uncaught SyntaxError: Missing initializer in const declaration
const USERNAME ;
Rest引數
(1)Rest就是為解決傳入的引數數量不一定, rest parameter(Rest 引數) 本身就是陣列,陣列的相關的方法都可以用。
注意:
(2)ES6推薦 使用rest引數。不要使用arguments
function fn(...arr) {
console.log(arr); //(5) [1, 2, 3, 4, 5]
}
console.log(fn(1, 2, 3, 4, 5));//undefined
arguments引數
function fn() {
var num = 0;
// 類陣列,但不是陣列
console.log(arguments);
// Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]
for (var i = 0; i < arguments.length; i++) {
num += arguments[i];
}
return num;
}
console.log(fn(1, 2, 3, 4, 5));//15
箭頭函式
定義
箭頭函式相當於匿名函式,並且簡化了函式定義。
並且沒有自己的this,arguments,super或 new.target。
這些函式表示式更適用於那些本來需要匿名函式的地方,並且它們不能用作建構函式。
格式
() => {}
使用
下面兩種定義方式效果相同。
let fn = function() {};
console.log(fn);//ƒ () {}
let fn = () => {};
console.log(fn);//() => {}
帶引數的箭頭函式
下面兩種寫法一樣
let fn = (a) => {
return a * 3;
}
console.log(fn(3));//9
let fn = a => a * 3;
console.log(fn(5));//15
返回值為物件的箭頭函式
let fn = () => ({
a: 1,
b: 2//設定預設值
})
console.log(fn());//{a: 1, b: 2}
let fn = (a, b) => {
return {
a:a,
b:b
}
}
console.log(fn(12,14));//{a: 12, b: 14}
使用箭頭函式進行陣列排序
思想:才用arr.sort(arr)函式進行排序。
var arr = [43, 5, 7, 43, 28, 986, 4, 1];
arr.sort(function(a, b) {
return a - b;
});
arr.sort((a, b) => a - b);
console.log(arr);//(8) [1, 4, 5, 7, 28, 43, 43, 986]
箭頭函式中的this
function fn() {
console.log(this); // obj
setTimeout(function() {
console.log(this); // window
}, 1000);
setTimeout(() => {
console.log(this); // obj
}, 1000);
}
var obj = {
fn: fn
}
obj.fn();
箭頭函式的引數
不能使用arguments,只能使用rest。
let fn = (...arr) => {
//console.log(arguments);
//Uncaught ReferenceError: arguments is not defined
console.log(arr);//(3) [1, 2, 3]
};
fn(1, 2, 3);
箭頭函式賦值不能用new
箭頭函式賦值物件不能用new,會報:Uncaught TypeError: Person is not a constructor。
let Person = function (){};//Person {}
//不能用new關鍵字,new宣告會報錯
//var Person = () => {};
//Uncaught TypeError: Person is not a constructor
console.log(new Person());
解構賦值
解構賦值語法是一個 Javascript 表示式,這使得可以將值從陣列或屬性從物件提取到不同的變數中。
let a = 1;
let b = 2;
let c = 3;
//上面賦值和下面賦值效果相同
let [a, b, c] = [1, 2, 3];
console.log(a, b, c);//1 2 3
//下面的陣列元素未賦值
let [y] = [];
console.log(y); // undefined
// 陣列元素給預設初始值
let [y = 3] = [];
console.log(y); // 3
let [y = 3] = [5];
console.log(y); // 5
//官方教程
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20
// Stage 3 proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); //{c: 30, d: 40}
注意:
特殊的物件賦值。
let {a: b} = {a: '1'}
console.log(b);//1
console.log(a)//Uncaught ReferenceError: a is not defined
let {random, floor} = Math;
console.log(random());//0.1054632111171554
console.log(floor(12.4));//12
物件內函式賦值
let U = {
add: function() {
console.log('add');
},
fn: function() {
console.log('fn');
}
};
U.add();//add
U.fn();//fn
//賦值
let {add, fn} = U;
add();//add
fn();//fn
物件解構賦值rest
let o = {a: 1, b: 2, c: 3, d: 4, f: 7};
let {b, ...pzh} = o;
console.log(b, pzh);//2 {a: 1, c: 3, d: 4, f: 7}
forEach迴圈遍歷陣列
形式:
arr.forEach(function (item, index, arr){});
作用:
遍歷陣列
引數說明
(1) 可以接收兩個引數,第一個引數是一個函式,就是陣列的每一項要執行這個函式。這個函式接收三個引數,分別是:陣列中的項,下標,陣列本身
(2)第二個引數是一個數組(可有可無)。如果有,前面函式中的this就指向這個陣列;如果沒有,前面函式的this就指向window。
let arr = [1, 2, 3, 4, 5, 6, 7];
arr.forEach(function(item, index) {
console.log(item+"============"+index);
//1============0
console.log(this);
//(7) [1, 2, 3, 4, 5, 6, 7]
},arr);
for-of迴圈遍歷陣列
let a = ['A', 'B', 'C'];
for (let attr of a) {
console.log(attr);//A B C
}