JS基礎(chǔ)知識總結(jié)(ECMA Script部分)

前言

最近總覺得自己所學(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í)行上下文的分類
  1. 全局:變量定義,函數(shù)聲明(一段<script>)
  2. 函數(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í)需要異步:
  1. 在可能發(fā)生等待的情況:在等待的過程中程序仍然要執(zhí)行其他操作。
  2. 等待過程中不能像 alert 一樣阻塞程序運(yùn)行。
  • 前端使用異步的場景:
  1. 定時(shí)任務(wù):setTimeout,setInterval
  2. 網(wǎng)絡(luò)請求:ajax 請求,動(dòng)態(tài) <img> 加載、腳本等文件下載和加載。
  3. 事件綁定

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

  1. forEach 遍歷所有元素
  2. every 判斷所有元素是否都符合條件
  3. some 判斷是否有至少一個(gè)元素符合條件
  4. sort 排序
  5. map 對元素重新組裝,生成新數(shù)組
  6. 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])
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容