A.函數
1.定義
(1)function abs(x) {...}
(2)var abs = function (x) {};
function (x) { ... }是一個匿名函數,它沒有函數名。可是,這個匿名函數賦值給了變量abs,因此,經過變量abs就能夠調用該函數。
上述兩種定義徹底等價,注意第二種方式按照完整語法須要在函數體末尾加一個;,表示賦值語句結束。調用時abs(10)
2.調用函數時,按順序傳入參數
(1)傳入的參數比定義的參數多,不會產生影響,正常返回
(2)傳入的參數比定義的參數少,如abs(),返回結果NaN,由於參數爲undefined,函數計算結果爲NaN
3.關鍵字arguments
只在函數內部起做用,而且永遠指向當前函數的調用者傳入的全部參數,功能至關於一個數組(但不是數組)
例:
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]);
}
4.rest參數(新定義參數,瀏覽器可能不會支持)
function foo(a, b, ...rest)
rest參數只能寫在最後,前面用...標識,從運行結果可知,傳入的參數先綁定a、b,多餘的參數以數組形式交給變量rest
若是傳入的參數連正常定義的參數都沒填滿,rest參數會接收一個空數組[]
5.return寫法注意事項
(1)正確寫法:
return { name: 'foo' };
或
return { // 這裏不會自動加分號,由於{表示語句還沒有結束
name: 'foo'
};
(2)錯誤寫法:
return // 這句執行時會自動添加分號,至關於return undefined;
{ name: 'foo' }; // 這行語句已經無法執行到了
B.變量做用域與解構賦值數組
1.若是內部函數和外部函數的變量名重名怎麼辦?
例:
function foo() {
var x = 1;
function bar() {
var x = 'A';
console.log('x in bar() = ' + x); // 'A'
}
console.log('x in foo() = ' + x); // 1
bar();
}瀏覽器
foo();
執行結果:
x in foo() = 1
x in bar() = A
這說明JavaScript的函數在查找變量時從自身函數定義開始,從「內」向「外」查找。
若是內部函數定義了與外部函數重名的變量,則內部函數的變量將「屏蔽」外部函數的變量。
2.變量提高
js函數定義有個特色,它會先掃描整個函數體的語句,把全部申明的變量「提高」到函數頂部
可是只自動提高了變量y的聲明,不會提高變量y的賦值
例:
function foo() {
var x = 'Hello, ' + y;
console.log(x);
var y = 'Bob';
}app
foo();
執行結果:
Hello, undefined
因此js最好在在函數內部首先申明全部變量,可以使用一個var定義全部用到的變量,可先不賦值
3.全局做用域
不在任何函數內定義的變量就具備全局做用域,全局做用域的變量實際上被綁定到window的一個屬性,window.變量名
4.名字空間
全局變量會綁定到window上,不一樣的JavaScript文件若是使用了相同的全局變量,或者定義了相同名字的頂層函數,都會形成命名衝突,而且很難被發現。
減小衝突的一個方法是把本身的全部變量和函數所有綁定到一個全局變量中。
例:
// 惟一的全局變量MYAPP:
var MYAPP = {};dom
// 其餘變量:
MYAPP.name = 'myapp';
MYAPP.version = 1.0;函數
// 其餘函數:
MYAPP.foo = function () {
return 'foo';
};
5.塊級做用域(關鍵字let,ES6新引入)
因爲JavaScript的變量做用域在函數內部,在for循環等語句塊中的i不是局部做用域的變量,在整個函數內都可使用
例:
function foo() {
for (var i=0; i<100; i++) {
...
}
i += 100; // 仍然能夠引用變量i
}
爲了解決塊級做用域,ES6引入了新的關鍵字let,用let替代var能夠申明一個塊級做用域的變量:網站
例:
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
// SyntaxError:
i += 1; //此時再調用變量i會報錯,使用let定義的變量i的做用於只存在於for循環中
}
6.常量定義(關鍵字 const,ES6新引入)
ES6之前一般用所有大寫的變量來表示「這是一個常量,不要修改它的值」:
例:
var PI = 3.14;
如今引入關鍵字const來申明常量(const與let都具備塊級做用域)
例:
const PI = 3.14;
PI = 3; // 某些瀏覽器不報錯,可是無效果!
PI; // 3.14
7.解構賦值(支持火狐、谷歌、edge瀏覽器)
可使用解構賦值,對多個變量同時賦值:
例:
(1)數組對變量同時賦值,使用[]括住變量
var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
(2)忽略前兩個元素,只對z賦值第三個元素,可忽略某個位置對指定位置賦值給變量
let [, , z] = ['hello', 'JavaScript', 'ES6'];
(3)數組自己嵌套
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
需注意嵌套位置的先後對應!!
(4)對象屬性對變量賦值(變量名須要與對象屬性名一致!!!不一致給變量賦值爲undefined),使用{}括住變量
例:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school'
};
var {name, age, passport} = person;
(5)嵌套的對象屬性對變量進行賦值,需注意嵌套位置的先後對應!!
例:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school',
address: {
city: 'Beijing',
street: 'No.1 Road',
zipcode: '100001'
}
};
var {name, address: {city, street}} = person;ui
(6)獲取對象屬性值,並更名
let {name, passport(對應對象屬性名):id(實際變量名)} = person;
注意: passport不是變量,而是爲了讓變量id得到passport屬性;至關於獲取對象屬性名爲passport的值,並賦值給變量id
(7)若對象屬性不存在,給變量賦值默認值
例:
// 若是person對象沒有single屬性,默認賦值爲true:
var {name, single=true} = person;
name; // '小明'
single; // true
(8)變量已申明作對象解構賦值
例:
var x, y; // 聲明變量:
({x, y} = { name: '小明', x: 100, y: 200}); //需在外面加上小括號,不然會報錯
8.解構賦值的使用場所
(1)交換兩個變量x和y的值:
var x=1, y=2;
[x, y] = [y, x]
(2)快速獲取當前頁面的域名和路徑:
var {hostname:domain, pathname:path} = location;
(3)若是一個函數接收一個對象做爲參數,那麼,可使用解構直接把對象的屬性綁定到變量中。
例如,下面的函數能夠快速建立一個Date對象:
function buildDate({year, month, day, hour=0, minute=0, second=0}) {
return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}
它的方便之處在於傳入的對象只須要year、month和day這三個屬性:
buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)
也能夠傳入hour、minute和second屬性:
buildDate({ year: 2017, month: 1, day: 1, hour: 20, minute: 15 });
// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)
spa
參考自廖雪峯老師的官方網站rest