前言
最近總覺得自己所學(xué)到的Javascript基礎(chǔ)知識不夠系統(tǒng),所以重新學(xué)習(xí)了Javascript的基本知識并有了這篇文章的產(chǎn)出,這篇文章主要是總結(jié)ECMA 262的的語法標(biāo)準(zhǔn)。
這篇文章的主要內(nèi)容是小結(jié)于慕課網(wǎng)的視頻課程《前端JavaScript面試技巧》, 如有錯(cuò)誤,請多指正,謝謝。
1. 變量類型和計(jì)算
1.1 按儲(chǔ)存方式區(qū)分變量類型
- 值類型:字符串(String)、數(shù)值(Number)、布爾值(Boolean)、Undefined、Null
占用空間固定,保存在棧中/保存與復(fù)制的是值本身/使用typeof檢測數(shù)據(jù)的類型 - 引用類型:對象(Object)、數(shù)組(Array)、函數(shù)(Function)
占用空間不固定,保存在堆中/保存與復(fù)制的是指向?qū)ο蟮囊粋€(gè)指針/使用instanceof檢測數(shù)據(jù)類型/使用new()方法構(gòu)造出的對象是引用型
另外,typeof運(yùn)算符結(jié)果:undefined,string,number,Boolean,object,function。(typeof只能區(qū)分值類型的詳細(xì)類型, 區(qū)分引用類型時(shí)只能區(qū)分出函數(shù))
1.2 JS中的內(nèi)置函數(shù)
Object, Array, Boolean, Number, String, Function, Date, RegExp
作用: 作為構(gòu)造函數(shù)使用
1.3 JS內(nèi)置對象
Math, JSON
1.4 如何理解Json
- JSON是一個(gè)JS對象,也是 一種數(shù)據(jù)格式
- 有兩個(gè)API
JSON.stringify({a:10,b:11})//把對象變成字符串
JSON.parse('{a:10,b:11}')//把字符串變成對象
1.5 強(qiáng)制類型轉(zhuǎn)換
1.5.1 if() {} if里會(huì)轉(zhuǎn)換成false
0: false
NaN: false
'': false
null: false
false: false
undefined: false
1.5.2 === 與==
- “==” 會(huì)強(qiáng)制類型轉(zhuǎn)換
- “===” 不會(huì)強(qiáng)制類型轉(zhuǎn)換
另外,何時(shí)用===,何時(shí)用==? 除了以下這種寫法用==,其余全部用===
if(obj.a == null){
//這里相當(dāng)于obj.a === null || obj.a === undefined 簡寫形式
//這是jquery源碼中推薦的寫法
}
1.6 構(gòu)造函數(shù)
1.6.1 構(gòu)造函數(shù)的特點(diǎn)
- 構(gòu)造函數(shù)的首字母必須大寫,用來區(qū)分于普通函數(shù)
- 內(nèi)部使用的this對象,來指向即將要生成的實(shí)例對象
- 使用New來生成實(shí)例對象
1.6.2 構(gòu)造函數(shù)的擴(kuò)展
- var a = {} 其實(shí)是var a = new Object()的語法糖
- var a = [] 其實(shí)是var a = new Array()的語法糖
- function Foo(){...} 其實(shí)是var Foo = new Function(...)
- 使用instanceof判斷一個(gè)函數(shù)是否是一個(gè)變量的構(gòu)造函數(shù), 如判斷一個(gè)變量是否為“數(shù)組”:
變量 instanceof Array
2. 原型和原理鏈
2.1原型
2.1.1 5條原型規(guī)則(是學(xué)習(xí)原型鏈的基礎(chǔ))
- 所有的引用類型(數(shù)組,對象,函數(shù)),都具有對象特性,即可自由擴(kuò)展屬性(除“null”以外)。
- 所有的引用類型,都有一個(gè)proto屬性(隱式原型屬性),屬性值是一個(gè)普通的對象。
- 所有的函數(shù),都有一個(gè)prototype屬性(顯式原型),屬性值是一個(gè)普通的對象。
- 所有的引用類型,proto屬性值指向它的構(gòu)造函數(shù)的“prototype”屬性值。(兩者完全相等)
- 當(dāng)試圖得到一個(gè)對象的某個(gè)屬性時(shí),如果這個(gè)對象本身沒有這個(gè)屬性,那么會(huì)去它的proto(即它的構(gòu)造函數(shù)的prototype)中尋找。
2.1.2 補(bǔ)充
- this:實(shí)例調(diào)用構(gòu)造函數(shù)的方法時(shí),this永遠(yuǎn)指向?qū)嵗陨?/li>
- 循環(huán)對象自身的屬性: for in
var item
for(item in f){
//高級瀏覽器已經(jīng)在for in中屏蔽了來自原型的屬性
//但是這里建議大家還是加上這個(gè)判斷,保證程序的健壯性
if(f,hasOwnProperty(item)){
console.log(item);
}
}
2.2原型鏈
- 原型鏈繼承的例子(之后補(bǔ)充)
instanceof
f instanceof Foo的判斷邏輯是:
1. f的__proto__一層一層往上,能否對應(yīng)到Foo.prototype
2. 再試著判斷f instanceof Object
2.3 New一個(gè)對象的過程
- 創(chuàng)建一個(gè)新對象
- this指向這個(gè)新對象
- 執(zhí)行代碼,即對this賦值
- 返回this
3. 閉包和作用域
3.1 作用域
3.1.1 執(zhí)行上下文
- 執(zhí)行上下文的分類
- 全局:變量定義,函數(shù)聲明(一段<script>)
- 函數(shù):變量定義、函數(shù)聲明、this、arguments (函數(shù)中)
另外, ”函數(shù)聲明“與“函數(shù)表達(dá)式”的區(qū)別:比如函數(shù)聲明是functon fn(){ }, 函數(shù)表達(dá)式是var fn = function(){};
fn()//不會(huì)報(bào)錯(cuò)
function fn(){
//函數(shù)聲明, 全局上下文提取到fn()函數(shù)
}
fn1()//會(huì)報(bào)錯(cuò)
var fn1 = function(){
//函數(shù)表達(dá)式,全局上下文會(huì)提取到fn1為undefined
}
fn('zhangsan')
function fn(name){
//函數(shù)
console.log(this);
console.log(arguments);
}
變量提升
執(zhí)行代碼塊的時(shí)候,會(huì)將申明變量、函數(shù)、argument等提前提取出來,然后再執(zhí)行代碼, 即變量提前,函數(shù)聲明提前-
this不同的使用場景
this要在執(zhí)行時(shí)才能確認(rèn)值,定義時(shí)無法確認(rèn)- 作為構(gòu)造函數(shù)執(zhí)行
- 作為對象屬性執(zhí)行
- 作為普通函數(shù)執(zhí)行
- call apply bind函數(shù)
var a = { name:'A', fn: function(){ console.log(this.name); console.log(this ) } } a.fn(); // this === a a.fn.call({name:'B'}) // this === {name:'B'} var fn1 = a.fn; fn1(); // this === window
3.2 作用域概念
作用域
全局作用域,函數(shù)作用域,塊級作用域(ES6: let, const)作用域鏈:
自由變量:當(dāng)前作用域沒有定義的變量
3.2 閉包
- 定義: 閉包是一個(gè)函數(shù)和函數(shù)所聲明的詞法環(huán)境的結(jié)合。
- 應(yīng)用場景:模塊化、封裝。
- 優(yōu)點(diǎn):封裝性強(qiáng),使得變量始終保持在內(nèi)存中。
- 缺點(diǎn):內(nèi)存的消耗導(dǎo)致的性能問題。
- 閉包創(chuàng)建:函數(shù)嵌套函數(shù),使得內(nèi)部函數(shù)返回出去,讓外部來訪問內(nèi)部的變量。
- 閉包的使用場景
1.函數(shù)作為一個(gè)返回值
2.函數(shù)作為參數(shù)傳遞。 - 閉包的例子:需注意, 一個(gè)函數(shù)的父級作用域是在它定義的時(shí)候的作用域,而非它執(zhí)行時(shí)候的作用域。
function F1(){
var a = 100;
return function(){
console.log(a) //100
}
}
var f1 = F1();
var a = 200
f1()
4. 異步和單線程
4.1 異步
- 異步定義
同步會(huì)阻塞后續(xù)程序代碼的執(zhí)行,而異步不會(huì)阻塞程序的運(yùn)行。 - 何時(shí)需要異步:
- 在可能發(fā)生等待的情況:在等待的過程中程序仍然要執(zhí)行其他操作。
- 等待過程中不能像 alert 一樣阻塞程序運(yùn)行。
- 前端使用異步的場景:
- 定時(shí)任務(wù):setTimeout,setInterval
- 網(wǎng)絡(luò)請求:ajax 請求,動(dòng)態(tài) <img> 加載、腳本等文件下載和加載。
- 事件綁定
4.2 單線程
由于js是單線程,在代碼執(zhí)行的時(shí)候又不能因?yàn)閳?zhí)行需要等待的代碼而造成阻塞,因此js會(huì)首先將無需等待的(同步)的代碼執(zhí)行完成后,來處理異步的代碼,如果達(dá)到異步代碼的執(zhí)行條件的話,就會(huì)執(zhí)行。
- setTimeout的例子
console.log(1)
setTimeout(function(){//因?yàn)閟etTimeout是異步,所以執(zhí)行時(shí)會(huì)被暫存起來
console.log(2)
}, 0)
console.log(3)
setTimeout(function(){
console.log((4))
},1000)
console.log(5)
//打印順序 1 3 5 2 4
5. 其他知識點(diǎn)-日期和Math,數(shù)組API,對象API
5.1 日期常用的API
Date.now() //獲取當(dāng)前時(shí)間毫秒數(shù)
var dt = new Date();
dt.getTime() //獲取毫秒數(shù)
dt.getFullYear() //年
dt.getMonth() //月(0-11)
dt.getDate() //日(0-31)
dt.getHours() //小時(shí)
dt.getMinutes() //分鐘(0-59)
dt.getSeconds() //秒(0-59)
5.2 Math常用的API
Math.random() //(0-1)
//常見的用法:清除緩存,比如說網(wǎng)站訪問鏈接,同一個(gè)鏈接會(huì)使同一個(gè)緩存,鏈接后面加上一個(gè)隨機(jī)數(shù),就可以清楚緩存
5.3數(shù)組API
- forEach 遍歷所有元素
- every 判斷所有元素是否都符合條件
- some 判斷是否有至少一個(gè)元素符合條件
- sort 排序
- map 對元素重新組裝,生成新數(shù)組
- filter 過濾符合條件的元素
5.4 對象API(for in)
var arr = [1, 2, 3]
arr.forEach(function(item, index){
console.log(index, item)
})
// 0 1
// 1 2
// 2 3
var arr = [1, 2, 3]
var result = arr.every(function(item, index){
if(item<4){
return true;
}
})
console.log(result) // true
var arr = [1, 2, 3]
var result2 = arr.some(function(item, index){
if(item<2){
return true
}
})
console.log(result2) //true
var arr = [5,4,3,2,1]
var arr2 = arr.sort(function(a,b){
//從小到大排序
console.log(a+'..'+b)
return a-b
//從大到小排序
// return b-a
})
console.log(arr2)
var arr = [1,2,3,4]
var arr2 = arr.map(function(item,index){
//將元素重新組裝,并返回
return '<b>'+item+'</b>'
})
console.log(arr2)
var arr = [1,2,3]
var arr2 = arr.filter(function(item,index){
//通過某一個(gè)條件過濾
if(item >= 2){
return true
}
})
console.log(arr2)
//對象代碼的例子
var obj={
x:100,
y:200,
z:300
}
var key
for(key in obj){
//hasOwnProperty判斷是不是obj原生的屬性
if(obj.hasOwnProperty(key)){
console.log(key,obj[key])
}
}