注:本文所有知識(shí)點(diǎn)總結(jié)或摘抄自廖雪峰javascript教程,點(diǎn)擊查看更詳細(xì)的講解。
1.javascript簡(jiǎn)介
-
ECMAScript
是一種語(yǔ)言標(biāo)準(zhǔn),而JavaScript
是網(wǎng)景公司對(duì)ECMAScript
標(biāo)準(zhǔn)的一種實(shí)現(xiàn)。可以說(shuō)javascript
語(yǔ)言的標(biāo)準(zhǔn)是ECMAScript
。
2. 入門(mén)基礎(chǔ)
- 在編寫(xiě)JavaScript代碼時(shí),經(jīng)常需要在
Console
運(yùn)行測(cè)試代碼,常用console.log()
。 - 對(duì)于復(fù)雜的層級(jí)嵌套,需要把部分代碼抽出來(lái),作為函數(shù)調(diào)用,以減少代碼的復(fù)雜程度。
- JavaScript嚴(yán)格區(qū)分大小寫(xiě),如果弄錯(cuò)了大小寫(xiě),程序?qū)?bào)錯(cuò)或者運(yùn)行不正常。
- JavaScript不區(qū)分整數(shù)和浮點(diǎn)數(shù),統(tǒng)一用
Number
表示。 - JavaScript有兩種比較運(yùn)算符:
第一種是==
比較,它會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型再比較,很多時(shí)候,會(huì)得到非常詭異的結(jié)果;
第二種是===
比較,它不會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類型,如果數(shù)據(jù)類型不一致,返回false,如果一致,再比較。 -
NaN
這個(gè)特殊的Number
與所有其他值都不相等,包括它自己:
NaN === NaN; // false
唯一能判斷NaN
的方法是通過(guò)isNaN()
函數(shù):
isNaN(NaN); // true
面試題中經(jīng)常出現(xiàn)null
undefined
NaN
相關(guān)知識(shí)點(diǎn)。
- 要比較兩個(gè)浮點(diǎn)數(shù)是否相等,只能計(jì)算它們之差的絕對(duì)值,看是否小于某個(gè)閾值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true
1 / 3 === (1 - 2 / 3); // false
-
null
表示一個(gè)“空”的值,它和0
以及空字符串' '
不同,0
是一個(gè)數(shù)值,''
表示長(zhǎng)度為0的字符串,而null
表示“空”。還有一個(gè)和null
類似的undefined
,它表示“未定義”。 - 數(shù)組的元素可以通過(guò)索引來(lái)訪問(wèn),索引的起始值為0。
- 對(duì)象是一組由鍵(字符串類型)-值(任意數(shù)據(jù)類型)組成的無(wú)序集合,每個(gè)鍵又稱為對(duì)象的屬性。
- 申明一個(gè)變量用
var
語(yǔ)句,變量名是大小寫(xiě)英文、數(shù)字、$和_的組合,不能用數(shù)字開(kāi)頭,不能是關(guān)鍵字。 - 變量本身的數(shù)據(jù)類型不固定的語(yǔ)言稱之為動(dòng)態(tài)語(yǔ)言,與之對(duì)應(yīng)的是靜態(tài)語(yǔ)言。
- 變量沒(méi)有通過(guò)
var
申明就被使用,那么該變量就自動(dòng)被申明為全局變量。特別需要注意i
的聲明。 - 啟用
strict
模式的方法是在JavaScript代碼的第一行寫(xiě)上:
'use strict';
- ES6新增了一種模板字符串代替加號(hào):
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}歲了!`;
alert(message);
- 常用的操作字符串方法
調(diào)用這些方法本身不會(huì)改變?cè)凶址膬?nèi)容,而是返回一個(gè)新字符串。
-
toUpperCase()
把一個(gè)字符串全部變?yōu)榇髮?xiě); -
toLowerCase()
把一個(gè)字符串全部變?yōu)樾?xiě); -
indexOf()
會(huì)搜索指定字符串出現(xiàn)的位置;
var s = 'hello, world';
s.indexOf('world'); // 返回7
s.indexOf('World'); // 沒(méi)有找到指定的子串,返回-1
-
substring()
返回指定索引區(qū)間的子串。
var s = 'hello, world'
s.substring(0, 5); // 從索引0開(kāi)始到5(不包括5),返回'hello'
s.substring(7); // 從索引7開(kāi)始到結(jié)束,返回'world'
- 如果通過(guò)索引給數(shù)組賦值時(shí),索引超過(guò)了范圍,會(huì)引起數(shù)據(jù)大小的變化:
var arr = [1, 2, 3];
arr[5] = 'x';
arr; // arr變?yōu)閇1, 2, 3, undefined, undefined, 'x']
- 常用的操作數(shù)組的方法
-
indexOf()
搜索一個(gè)指定的元素的位置;
var arr = [10, 20, '30', 'xyz'];
arr.indexOf(10); // 元素10的索引為0
-
slice()
截取Array
的部分元素,然后返回一個(gè)新的Array
:
var arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
arr.slice(0, 3); // 從索引0開(kāi)始,到索引3結(jié)束,但不包括索引3: ['A', 'B', 'C']
不給slice()
傳遞任何參數(shù)來(lái)復(fù)制一個(gè)Array
。
-
push()
向Array
的末尾添加若干元素; -
pop()
則把Array
的最后一個(gè)元素刪除掉; -
unshift()
向Array
的頭部添加若干元素; -
shift()
則把Array
的第一個(gè)元素刪除掉; -
sort()
會(huì)直接修改當(dāng)前Array
的元素位置,對(duì)當(dāng)前Array
進(jìn)行排序; -
reverse()
把整個(gè)Array
的元素給掉個(gè)個(gè),也就是反轉(zhuǎn); -
splice()
方法是修改Array
的“萬(wàn)能方法”,它可以從指定的索引開(kāi)始刪除若干元素,然后再?gòu)脑撐恢锰砑尤舾稍兀?/li>
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 從索引2開(kāi)始刪除3個(gè)元素,然后再添加兩個(gè)元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回刪除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只刪除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不刪除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因?yàn)闆](méi)有刪除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
-
concat()
方法把當(dāng)前的Array
和另一個(gè)Array
連接起來(lái),并返回一個(gè)新的Array
; -
join()
方法把當(dāng)前Array
的每個(gè)元素都用指定的字符串連接起來(lái),然后返回連接后的字符串:
var arr = ['A', 'B', 'C', 1, 2, 3];
arr.join('-'); // 'A-B-C-1-2-3'
如果Array
的元素不是字符串,將自動(dòng)轉(zhuǎn)換為字符串后再連接。
- JavaScript中能用
.
的地方就能用[ ]
代替:
xiaohong['name']; // '小紅'
xiaohong.name; // '小紅'
- JavaScript規(guī)定,訪問(wèn)不存在的屬性不報(bào)錯(cuò),而是返回
undefined
:
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
- 檢測(cè)
xiaoming
是否擁有某一屬性:
- 可以用in操作符(無(wú)法確定屬性來(lái)自本身還是來(lái)自繼承)
'name' in xiaoming; // true
'grade' in xiaoming; // false
- 可以用hasOwnProperty()方法(判斷一個(gè)屬性是否自身?yè)碛校?/li>
var xiaoming = {
name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
-
if...else...
語(yǔ)句的執(zhí)行特點(diǎn)是二選一,在多個(gè)if...else...
語(yǔ)句中,如果某個(gè)條件成立,則后續(xù)就不再繼續(xù)判斷了。 - JavaScript把
null
、undefined
、0
、NaN
和空字符串''
視為false
,其他值一概視為true
。 -
for
循環(huán)的一個(gè)變體是for ... in
循環(huán),它可以把一個(gè)對(duì)象的所有屬性依次循環(huán)出來(lái):
var o = {
name: 'Jack',
age: 20,
city: 'Beijing'
};
for (var key in o) {
alert(key); // 'name', 'age', 'city'
}
- 由于
Array
也是對(duì)象,而它的每個(gè)元素的索引被視為對(duì)象的屬性,因此,for ... in
循環(huán)可以直接循環(huán)出Array
的索引:
var a = ['A', 'B', 'C'];
for (var i in a) {
alert(i); // '0', '1', '2'
alert(a[i]); // 'A', 'B', 'C'
}
for ... in
對(duì)Array
的循環(huán)得到的是String
而不是Number
。
- Map是一組鍵(key)值(value)對(duì)的結(jié)構(gòu),具有極快的查找速度。
假設(shè)要根據(jù)同學(xué)的名字查找對(duì)應(yīng)的成績(jī),如果用Array
實(shí)現(xiàn),需要兩個(gè)Array
:
var names = ['Michael', 'Bob', 'Tracy'];
var scores = [95, 75, 85];
給定一個(gè)名字,要查找對(duì)應(yīng)的成績(jī),就先要在names
中找到對(duì)應(yīng)的位置,再?gòu)?code>scores取出對(duì)應(yīng)的成績(jī),Array
越長(zhǎng),耗時(shí)越長(zhǎng)。
如果用Map
實(shí)現(xiàn),只需要一個(gè)“名字”-“成績(jī)”的對(duì)照表,直接根據(jù)名字查找成績(jī),無(wú)論這個(gè)表有多大,查找速度都不會(huì)變慢。用JavaScript寫(xiě)一個(gè)Map
如下:
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
-
Set
和Map
類似,也是一組key
的集合,但不存儲(chǔ)value
。 -
Map
和Set
是ES6標(biāo)準(zhǔn)新增的數(shù)據(jù)類型。 - 遍歷
Array
可以采用下標(biāo)循環(huán),遍歷Map
和Set
就無(wú)法使用下標(biāo)。ES6標(biāo)準(zhǔn)引入了新的iterable
類型,Array
、Map
和Set
都屬于iterable
類型。 -
iterable
類型的集合可以通過(guò)新的for ... of
循環(huán)來(lái)遍歷。for ... of循環(huán)和for ... in循環(huán)有何區(qū)別? - 函數(shù)體內(nèi)部的語(yǔ)句執(zhí)行到
return
時(shí),函數(shù)就執(zhí)行完畢,并將結(jié)果返回。如果沒(méi)有return
,返回結(jié)果是undefined
。 -
arguments
只在函數(shù)內(nèi)部起作用,指向當(dāng)前函數(shù)的調(diào)用者傳入的所有參數(shù)。利用其可以獲得調(diào)用者傳入的所有參數(shù),最常用于判斷傳入?yún)?shù)的個(gè)數(shù)。 - 小心return語(yǔ)句(JavaScript引擎有一個(gè)在行末自動(dòng)添加分號(hào)的機(jī)制,這可能讓你栽到return語(yǔ)句的一個(gè)大坑):
function foo() {
return { name: 'foo' };
}
foo(); // { name: 'foo' }
function foo() {
return
{ name: 'foo' };
}
foo(); // undefined
- 定義一個(gè)計(jì)算圓面積的函數(shù)
square()
,它有兩個(gè)參數(shù):- r: 表示圓的半徑;
- pi: 表示π的值,如果不傳,則默認(rèn)3.14。
一般寫(xiě)法:
function square(r, pi) {
var r,pi;
if(pi) {
return pi*r*r;
}
else {
return 3.14*r*r;
}
經(jīng)典寫(xiě)法:
function square(r, pi) {
var r,pi;
r = (r || 0) > 0 ? r : 0;
pi = pi || 3.14;
return pi*r*r;
}
- 用
var
申明的變量是有作用域的:
- 變量在函數(shù)體內(nèi)部申明,則該變量的作用域?yàn)檎麄€(gè)函數(shù)體,在函數(shù)體外不可引用該變量;
- 不同函數(shù)內(nèi)部的同名變量互相獨(dú)立,互不影響;
- 嵌套函數(shù)時(shí),內(nèi)部函數(shù)可以訪問(wèn)外部函數(shù)定義的變量,反過(guò)來(lái)則不行;
- 內(nèi)部函數(shù)定義了與外部函數(shù)重名的變量,則內(nèi)部函數(shù)的變量將“屏蔽”外部函數(shù)的變量。
(這說(shuō)明JavaScript的函數(shù)在查找變量時(shí)從自身函數(shù)定義開(kāi)始,從“內(nèi)”向“外”查找。)
- 函數(shù)會(huì)先掃描整個(gè)函數(shù)體的語(yǔ)句,把所有申明的變量“提升”到函數(shù)頂部,但不會(huì)提升變量的賦值:
function foo() {
var x = 'Hello, ' + y;
alert(x);
var y = 'Bob';
}
foo(); //Hello, undefined
- 不報(bào)錯(cuò):變量
y
在稍后申明了。 - 顯示
Hello, undefined
:說(shuō)明變量y的值為undefined。JavaScript引擎自動(dòng)提升了變量y
的聲明,但不會(huì)提升變量y
的賦值。
- 全局作用域的變量實(shí)際上被綁定到
window
的一個(gè)屬性。
直接訪問(wèn)全局變量a
和訪問(wèn)window.a
是完全一樣的。 - 用
let
替代var
可以申明一個(gè)塊級(jí)作用域的變量。 - ES6標(biāo)準(zhǔn)引入了新的關(guān)鍵字
const
來(lái)定義常量,const
與let
都具有塊級(jí)作用域。 - 通常用全部大寫(xiě)的變量來(lái)表示“這是一個(gè)常量,不要修改它的值”:
const PI = 3.14;
。 - 綁定到對(duì)象上的函數(shù)稱為方法,和普通函數(shù)沒(méi)啥區(qū)別。
- 在一個(gè)方法內(nèi)部,
this
是一個(gè)特殊變量,它始終指向當(dāng)前對(duì)象。
這里有坑:詳情移步 廖雪峰-方法
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25, 正常結(jié)果
getAge(); // NaN
- 以對(duì)象的方法形式調(diào)用,比如
xiaoming.age()
,該函數(shù)的this指向被調(diào)用的對(duì)象,也就是xiaoming
。 - 如果單獨(dú)調(diào)用函數(shù),比如
getAge()
,此時(shí),該函數(shù)的this
指向全局對(duì)象,也就是window
。 - 即使把
xiaoming.age()
先給函數(shù),再調(diào)用也不行。
var fn = xiaoming.age; // 先拿到xiaoming的age函數(shù)
fn(); // NaN
- ECMA決定,在
strict
模式下讓函數(shù)的this
指向undefined
。 - 在方法函數(shù)內(nèi)部定義的函數(shù)內(nèi)
this
指向undefined
。
- 要指定函數(shù)的
this
指向哪個(gè)對(duì)象,可以用函數(shù)本身的apply
方法,它接收兩個(gè)參數(shù),第一個(gè)參數(shù)就是需要綁定的this
變量,第二個(gè)參數(shù)是Array
,表示函數(shù)本身的參數(shù)。 - 另一個(gè)與
apply()
類似的方法是call()
,唯一區(qū)別是:
-
apply()
把參數(shù)打包成Array
再傳入; -
call()
把參數(shù)按順序傳入
-
js調(diào)用函數(shù)時(shí)加括號(hào)與不加括號(hào)的區(qū)別:
函數(shù)名其實(shí)就是指向函數(shù)體的指針 ,
- 不加括號(hào), 可以認(rèn)為是查看該函數(shù)的完整信息;
- 加括號(hào) 表示立即調(diào)用(執(zhí)行)這個(gè)函數(shù)里面的代碼(花括號(hào)部分的代碼);
- 不加括號(hào)傳參,相當(dāng)于傳入函數(shù)整體 ;
- 加括號(hào)傳參,相當(dāng)于將函數(shù)的返回值作為參數(shù)。
-
Array
的map()
方法
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
-
reduce()
把結(jié)果繼續(xù)和序列的下一個(gè)元素做累積計(jì)算:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
-
filter()
和map()
類似也接收一個(gè)函數(shù),filter()
把傳入的函數(shù)依次作用于每個(gè)元素,然后根據(jù)返回值是true
還是false
決定保留還是丟棄該元素。
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
- sort()方法也是一個(gè)高階函數(shù),它還可以接收一個(gè)比較函數(shù)來(lái)實(shí)現(xiàn)自定義的排序。
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); // [1, 2, 10, 20]
- 閉包,我不敢說(shuō)太多,因?yàn)樽约阂矝](méi)有明白得太清楚,但是我感覺(jué)這幾篇文章值得看。javascript深入理解js閉包
深入理解javascript原型和閉包(完結(jié)) - 箭頭函數(shù)相當(dāng)于匿名函數(shù),并且簡(jiǎn)化了函數(shù)定義,兩種格式:
- 簡(jiǎn)化格式
- 單參數(shù)
x => x * x
上面的箭頭函數(shù)相當(dāng)于:
function (x) {
return x * x;
}
* 多參數(shù)
(x, y) => x * x + y * y
* 無(wú)參數(shù)
() => 3.14
- 標(biāo)準(zhǔn)格式
x => {
if (x > 0) {
return x * x;
}
else {
return - x * x;
}
}
不要使用·new Number()·、·new Boolean()·、·new String()·創(chuàng)建包裝對(duì)象;
用
parseInt()
或parseFloat()
來(lái)轉(zhuǎn)換任意類型到number
;用
String()
來(lái)轉(zhuǎn)換任意類型到string
,或者直接調(diào)用某個(gè)對(duì)象的toString()
方法;通常不必把任意類型轉(zhuǎn)換為
boolean
再判斷,因?yàn)榭梢灾苯訉?xiě)if (myVar) {...}
;typeof
操作符可以判斷出number
、boolean
、string
、function
和undefined
;判斷Array要使用
Array.isArray(arr)
;判斷
null
請(qǐng)使用myVar === null
;判斷某個(gè)全局變量是否存在用
typeof window.myVar === 'undefined'
;函數(shù)內(nèi)部判斷某個(gè)變量是否存在用
typeof myVar === 'undefined'
。Date對(duì)象用來(lái)表示日期和時(shí)間。要獲取系統(tǒng)當(dāng)前時(shí)間,用:
var now = new Date();
now; // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
now.getFullYear(); // 2015, 年份
now.getMonth(); // 5, 月份,注意月份范圍是0~11,5表示六月
now.getDate(); // 24, 表示24號(hào)
now.getDay(); // 3, 表示星期三
now.getHours(); // 19, 24小時(shí)制
now.getMinutes(); // 49, 分鐘
now.getSeconds(); // 22, 秒
now.getMilliseconds(); // 875, 毫秒數(shù)
now.getTime(); // 1435146562875, 以number形式表示的時(shí)間戳
- 正則表達(dá)式的設(shè)計(jì)思想是用一種描述性的語(yǔ)言來(lái)給字符串定義一個(gè)規(guī)則,凡是符合規(guī)則的字符串,我們就認(rèn)為它“匹配”了,否則,該字符串就是不合法的。
- js正則表達(dá)式基本語(yǔ)法(精粹)
- 對(duì)象的兩個(gè)基本概念:
- 類:類是對(duì)象的類型模板,例如,定義Student類來(lái)表示學(xué)生,類本身是一種類型,Student表示學(xué)生類型,但不表示任何具體的某個(gè)學(xué)生;
- 實(shí)例:實(shí)例是根據(jù)類創(chuàng)建的對(duì)象,例如,根據(jù)Student類可以創(chuàng)建出xiaoming、xiaohong、xiaojun等多個(gè)實(shí)例,每個(gè)實(shí)例表示一個(gè)具體的學(xué)生,他們?nèi)紝儆赟tudent類型。
JavaScript不區(qū)分類和實(shí)例的概念,而是通過(guò)原型(prototype)來(lái)實(shí)現(xiàn)面向?qū)ο缶幊獭?/li>
-
window
對(duì)象不但充當(dāng)全局作用域,而且表示瀏覽器窗口。有innerWidth
和innerHeight
屬性,可以獲取瀏覽器窗口的內(nèi)部寬度和高度。內(nèi)部寬高是指除去菜單欄、工具欄、邊框等占位元素后,用于顯示網(wǎng)頁(yè)的凈寬高。outerWidth
和outerHeight
屬性,可以獲取瀏覽器窗口的整個(gè)寬高。 - DOM是一個(gè)樹(shù)形結(jié)構(gòu)。操作一個(gè)DOM節(jié)點(diǎn)實(shí)際上就是這么幾個(gè)操作:
- 更新:更新該DOM節(jié)點(diǎn)的內(nèi)容;
-
innerHTML
可以修改一個(gè)DOM節(jié)點(diǎn)的文本內(nèi)容,還可以通過(guò)HTML片段修改DOM節(jié)點(diǎn)內(nèi)部的子樹(shù); -
innerText
或textContent
修改一個(gè)DOM節(jié)點(diǎn)的文本內(nèi)容,無(wú)法設(shè)置任何HTML標(biāo)簽。innerText不返回隱藏元素的文本,而textContent返回所有文本。
-
- 遍歷:遍歷該DOM節(jié)點(diǎn)下的子節(jié)點(diǎn);
- 添加:在該DOM節(jié)點(diǎn)下新增一個(gè)子節(jié)點(diǎn);
- 如果這個(gè)DOM節(jié)點(diǎn)是空的,直接使用
innerHTML = '<span>child</span>'
,不是空的,那就不能這么做,因?yàn)閕nnerHTML會(huì)直接替換掉原來(lái)的所有子節(jié)點(diǎn); - 使用
appendChild
,把一個(gè)子節(jié)點(diǎn)添加到父節(jié)點(diǎn)的最后一個(gè)子節(jié)點(diǎn);
*使用insertBefore
,把子節(jié)點(diǎn)插入到指定的位置。
- 如果這個(gè)DOM節(jié)點(diǎn)是空的,直接使用
- 刪除:將該節(jié)點(diǎn)從HTML中刪除。
- 要?jiǎng)h除一個(gè)節(jié)點(diǎn),首先要獲得該節(jié)點(diǎn)本身以及它的父節(jié)點(diǎn),然后,調(diào)用父節(jié)點(diǎn)的
removeChild
把自己刪掉
- 要?jiǎng)h除一個(gè)節(jié)點(diǎn),首先要獲得該節(jié)點(diǎn)本身以及它的父節(jié)點(diǎn),然后,調(diào)用父節(jié)點(diǎn)的
感謝各位閱讀,歡迎指正錯(cuò)誤!!!