什么是 javascript
ECMAScript 是一個國際通過的標(biāo)準(zhǔn)化腳本語言。JavaScript 由 ECMAScript 和 DOM、BOM 三者組成。
ECMAScript:ECMAScript 是 JavaScript 的語言規(guī)范,JavaScript 是 ECMAScript 的實現(xiàn)和擴(kuò)展。
DOM:文檔對象模型
BOM:瀏覽器對象模型
數(shù)據(jù)類型
基本數(shù)據(jù)類型
null
undefinde
boolean
string
number
symbol(ES6新增)
引用數(shù)據(jù)類型(復(fù)雜數(shù)據(jù)類型)
function
Array
Object
Map(ES6新增)
Set(ES6新增)
判斷數(shù)據(jù)類型的方法
typeof 檢測數(shù)據(jù):
缺點:無法判斷null和object
返回值:數(shù)據(jù)類型
檢測數(shù)據(jù) instanceof:
缺點:無法判斷字面量創(chuàng)建的基本數(shù)據(jù)類型
返回值:boolean
原理:實際上就是查找目標(biāo)對象的原型鏈
檢測數(shù)據(jù).constructor.name:
返回值:數(shù)據(jù)類型
Object.prototype.toString.call(檢測數(shù)據(jù)):
返回值:"[object Number]"
事件循環(huán)機(jī)制
概念:同步和異步任務(wù)分別進(jìn)入不同的執(zhí)行環(huán)境,同步的進(jìn)入主線程,即主執(zhí)行棧,異步的進(jìn)入任務(wù)隊列(Event Queue )。
主線程內(nèi)的任務(wù)執(zhí)行完畢為空,會去任務(wù)隊列讀取對應(yīng)的任務(wù),推入主線程執(zhí)行。 上述過程的不斷重復(fù)就是我們說的 Event Loop (事件循環(huán))。
宏任務(wù)(Macro Task ):script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環(huán)境)
微任務(wù)(Micro Task):Promise、MutaionObserver、process.nextTick(Node.js 環(huán)境)
在異步任務(wù)中,采取一個先進(jìn)先出的一個原則;微任務(wù)先于宏任務(wù)執(zhí)行原則
垃圾回收機(jī)制和內(nèi)存泄漏
什么是垃圾回收機(jī)制:在JavaScript中,一般來說沒有被引用的對象就是垃圾,就是要被清除;
有個例外如果幾個對象引用形成一個環(huán),互相引用,但根訪問不到它們,這幾個對象也是垃圾,也要被清除。
如何執(zhí)行:JavaScript 引擎中有一個后臺進(jìn)程稱為垃圾回收器,它會通過‘標(biāo)記-清除 算法’監(jiān)視所有對象,并刪除那些不可訪問的對象。
什么叫做根:本地函數(shù)的局部變量和參數(shù)。當(dāng)前嵌套調(diào)用鏈上的其他函數(shù)的變量和參數(shù)。全局變量。還有一些其他的,內(nèi)部的
內(nèi)存泄露:是指當(dāng)一塊內(nèi)存不再被應(yīng)用程序使用的時候,由于某種原因,這塊內(nèi)存沒有返還給操作系統(tǒng)或者內(nèi)存池的現(xiàn)象。
閉包常駐內(nèi)存
閉包
閉包==>就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。(定義在一個函數(shù)內(nèi)部的函數(shù))
函數(shù)內(nèi)部聲明變量的時候,一定要使用var命令。如果不用的話,你實際上聲明了一個全局變量!
一個是前面提到的可以讀取函數(shù)內(nèi)部的變量,另一個就是讓這些變量的值始終保持在內(nèi)存中。
遞歸
遞歸本質(zhì)上是將原來的問題,轉(zhuǎn)化為更小的同一問題
一個函數(shù)不斷的調(diào)用自己
原型和原型鏈、構(gòu)造函數(shù)、實例對象、原型對象
構(gòu)造函數(shù):每一個函數(shù)或者對象在被創(chuàng)建時,都會添加一個prototype屬性,默認(rèn)指向它的原型對象。
原型對象:原型對象的constructor 指向所創(chuàng)建它的構(gòu)造函數(shù)
實例對象:構(gòu)造函數(shù)通過new方法創(chuàng)建一個實例對象;實例對象上的__proto__默認(rèn)指向它的原型對象。
原型:js中萬物皆對象,每一個對象都有自己的屬性和方法,因為要解決屬性或方法的共享問題,所以就出現(xiàn)了原型。
原型鏈:js在查找屬性或方法的過程中,如果在自己的屬性中找不到就會沿著__proto__去找原型對象,
如果原型對象中還找不到,就繼續(xù)沿著原型對象的__proto__中查找,這種通過__proto__查找的過程就叫做原型鏈
創(chuàng)建對象的方式
字面量隱式創(chuàng)建:var obj = new Object()
字面量創(chuàng)建對象:var c = {a: 1,b: 2}
Object.assign():通過復(fù)制一個或多個對象來創(chuàng)建一個新的對象。
Object.create():使用指定的原型對象和屬性創(chuàng)建一個新對象。
使用 class 關(guān)鍵字創(chuàng)建的對象
復(fù)制對象的方式
1、JSON.parse(JSON.stringify(obj)) 深復(fù)制
2、object.assign()
3、for...in...
4、{...}
深拷貝和淺拷貝
淺拷貝是拷貝一層,基本數(shù)據(jù)類型就是值的復(fù)制,對象級別的就拷貝引用;
==>用 = 號賦值引用地址
==>for...in...存在嵌套對象時
===>Object.assign()存在嵌套對象時
===>{...}一層時
深拷貝是拷貝多層,每一級別的數(shù)據(jù)都會拷貝出來;在引用數(shù)據(jù)類型嵌套引用數(shù)據(jù)類型
==>JSON.parse(JSON.stringify())
==>缺點:時間對象字符串的形式,RegExp空對象,丟棄對象的constructor
==>for…in不存在嵌套對象時
==>Object.assign()不存在嵌套對象時
==>遞歸的形式
===>{...}多層時
==>數(shù)組的slice方法
==>數(shù)組的concat的方法
判斷對象為空的方法
1、Object.keys()
==>返回一個包含所有給定對象自身可枚舉屬性名稱的數(shù)組。
2、Object.getOwnPropertySymbols()
==>返回一個數(shù)組,它包含了指定對象自身所有的符號屬性。
3、將json對象轉(zhuǎn)化為json字符串,再判斷該字符串是否為"{}"
4、for in 循環(huán)判斷
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;
}
普通函數(shù)和箭頭函數(shù)的區(qū)別
寫法不一樣:箭頭函數(shù)使用箭頭定義,普通函數(shù)沒有
箭頭函數(shù)的this指向取決于它上一級的this指向,普通函數(shù)的this指向調(diào)用他的對象
箭頭函數(shù)不能作為構(gòu)造函數(shù),不能使用new
箭頭函數(shù)沒有原型,不能繼承
箭頭函數(shù)沒有arguments,如果要用,可以用剩余運算符代替 (注意在node環(huán)境下是有arguments的)
箭頭函數(shù)為匿名函數(shù),普通函數(shù)可以為具名函數(shù),也可為匿名函數(shù)(自執(zhí)行函數(shù))
改變 this 指向的方法
obj.myfun.call(db, '城都', '上海') //junjun
obj.myfun.apply(db, ['城都', '上海']) //junjun //除了第一個是this指向,其他參數(shù)必須放在一個數(shù)組里面?zhèn)鬟M(jìn)去
obj.myfun.bind(db, '城都', '上海')() //junjun 返回的是一個函數(shù)需要調(diào)用才會執(zhí)行
回流和重繪
1、html被html解析器解析成DOM樹
2、css被css解析器解析成CSS規(guī)則樹
3、將HTML和CSS合成render樹
4、生成布局(flow),即將所有渲染樹的所有節(jié)點進(jìn)行平面合成
5、將布局繪制(repaint)到屏幕上
重繪(repaint):當(dāng)元素樣式的改變不影響頁面布局時,比如元素的顏色,瀏覽器將對元素進(jìn)行的更新,稱之為重繪
回流(reflow):也叫做重排。當(dāng)元素的尺寸或者位置發(fā)生了變化,就需要重新計算渲染樹,這就是回流,比如元素的寬高、位置,瀏覽器會重新渲染頁面,稱為回流,又叫重排(layout)。
關(guān)系:回流必定會觸發(fā)重繪,重繪不一定會觸發(fā)回流。重繪的開銷較小,回流的代價較高。
如和減少回流和重繪?使用class類名來控制樣式的改變;對于復(fù)雜的動畫效果可以使其脫離文檔流;免循環(huán)操作DOM/避免循環(huán)讀取offsetLeft等屬性
cookies,sessionStorage 和 localStorage
cookie:生命周期為人為設(shè)置,在過期時間之前都是有效的。每次http請求都會攜帶cookie。大小約為4kb
sessionStorage:生命周期為僅在當(dāng)前瀏覽器窗口關(guān)閉之前有效,關(guān)閉頁面或者瀏覽器會被清除。不參與和服務(wù)器的通信。大小約5M或者更大
localStorage:永久有效,窗口或者瀏覽器關(guān)閉也會一直保存,除非手動永久清除。不參與和服務(wù)器的通信。大小約5M或者更大
removeItem()/setItem()/clear()/getItem()
promise 的理解
1、promise是一個構(gòu)造函數(shù),通過new方法可以用來創(chuàng)建一個Promise對象
2、Promise是ES6新增的解決傳統(tǒng)的回調(diào)地獄的解決方案,promise用來將這種繁雜的做法簡化,
可以將異步操作以同步的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù),讓程序更具備可讀性,可維護(hù)性。
3、promise有三種狀態(tài),peddding reslove rejected,狀態(tài)一旦改變,就無法再次改變狀態(tài),一個promise對象只能改變一次
4、promise.all()用于將多個 Promise 實例,包裝成一個新的 Promise 實例
==> promise1和promise2都成功才會調(diào)用success1
5、Promise.race()方法同樣是將多個 Promise 實例,包裝成一個新的 Promise 實例
==>promise1和promise2只要有一個成功就會調(diào)用success1
ES6 的新特性
promise
class類
let,const,
結(jié)構(gòu)賦值
箭頭函數(shù)
函數(shù)參數(shù)的默認(rèn)值default
Spread / Rest 操作符
==>rest操作符讓函數(shù)的所有參數(shù)可由一個變量統(tǒng)一接收 ,幫助我們創(chuàng)建更加靈活的函數(shù)
==>spread運算符比較經(jīng)常數(shù)組的解析與構(gòu)造
for...of 和 for...in
==>for…in是遍歷數(shù)組(盡量不用)、對象的key:不僅遍歷數(shù)字鍵名,還會遍歷手動添加的其它鍵,甚至包括原型鏈上的鍵
==>for…of是遍歷數(shù)組,類數(shù)組,Map,Set的value
對象超類:使用super關(guān)鍵字可以調(diào)用父級的方法
==>Object.setPrototypeOf(child,parent):設(shè)置置child的對象的原型(即內(nèi)部 [[Prototype]] 屬性)
數(shù)字前面添加 0o 或者0O 即可將其轉(zhuǎn)換為八進(jìn)制值:
變量提升
預(yù)編譯階段和執(zhí)行階段
js引擎在正式執(zhí)行代碼前會進(jìn)行一次預(yù)編譯,會把var所定義的變量以及函數(shù)當(dāng)前作用域的頂部聲明。
函數(shù)提升
JavaScript中的函數(shù)是一等公民,函數(shù)聲明的優(yōu)先級最高,會被提升至當(dāng)前作用域最頂端
函數(shù)提升會在變量提升之前
作用域和作用域鏈
JavaScript有全局作用域和函數(shù)作用域、塊作用域。
1、作用域最大的用處就是隔離變量,不同作用域下同名變量不會有沖突。
2、所有末定義直接賦值的變量自動聲明為擁有全局作用域
3、作用域是分層的,內(nèi)層作用域可以訪問外層作用域的變量,反之則不行。
作用域鏈:如果父級也沒呢?再一層一層向上尋找,直到找到全局作用域還是沒找到,就宣布放棄。
這種一層一層的關(guān)系,就是 作用域鏈 。
執(zhí)行上下文在運行時確定,隨時可能改變;作用域在定義時就確定,并且不會改變。
let、var 和 const 的區(qū)別
let/const 聲明并不會被提升到當(dāng)前代碼塊的頂部,因此你需要手動將 let/const 聲明放置到頂部,
以便讓變量在整個代碼塊內(nèi)部可用。
塊級作用域:1、在一個函數(shù)內(nèi)部;2、在一個代碼塊(由一對花括號包裹)內(nèi)部
禁止重復(fù)聲明
var定義的變量,沒有塊的概念,可以跨塊訪問, 不能跨函數(shù)訪問。
let定義的變量,只能在塊作用域里訪問,不能跨塊訪問,也不能跨函數(shù)訪問。
const用來定義常量,使用時必須初始化(即必須賦值),只能在塊作用域里訪問,而且不能修改。
this 指向
1.在瀏覽器中,在全局范圍內(nèi)this 指向window對象
2.在函數(shù)中,this永遠(yuǎn)指向最后調(diào)用他的那個對象;
3.構(gòu)造函數(shù)中,this指向new出來的那個新的對象;
4.call、apply、bind中的this被強(qiáng)綁定在指定的那個對象上;
==>js給函數(shù)內(nèi)置的一些API,調(diào)用他們可以為函數(shù)指定this的執(zhí)行,同時也可以傳參。
5.箭頭函數(shù)中this比較特殊,箭頭函數(shù)this為父作用域的this,不是調(diào)用時的this.要知道前四種方式,都是調(diào)用時確定,也就是動態(tài)的,而箭頭函數(shù)的this指向是靜態(tài)的,聲明的時候就確定了下來;
具名函數(shù)和匿名函數(shù)
具名函數(shù)和匿名函數(shù)的區(qū)別:看關(guān)鍵字·function后的函數(shù)名稱,有函數(shù)名稱的是具名函數(shù),沒有的是匿名函數(shù)
立即調(diào)用函數(shù)表達(dá)式
(function(){
console.log('自執(zhí)行函數(shù)')
}()}
GET 和 POST 的區(qū)別
1、get請求是獲取數(shù)據(jù)的,而post請求是提交數(shù)據(jù)的。
2、get請求能被緩存,post請求不能被緩存
3、get請求對數(shù)據(jù)長度的限制;當(dāng)發(fā)送數(shù)據(jù)時,GET 方法向 URL 添加數(shù)據(jù)get請求的傳送數(shù)據(jù)會拼接在url后面
4、GET在瀏覽器回退時是無害的,而POST會再次提交請求。
5、GET比POST更不安全,因為參數(shù)直接暴露在URL上,所以不能用來傳遞敏感信息。
6、GET參數(shù)通過URL傳遞,POST放在Request body中。
同源策略
同源策略是瀏覽器最核心也最基本的安全功能,是禁止瀏覽器跨域請求數(shù)據(jù),目的是保護(hù)信息安全。
域名、協(xié)議、端口號
跨域
域名、協(xié)議、端口號三者有一個不同的話都是屬于一個跨域行為
nginx代理跨域
通過jsonp跨域
postMessage跨域
document.domain + iframe跨域
location.hash + iframe
window.name + iframe跨域
輸入 url 后會發(fā)生什么?
1.DNS域名解析;
2.建立TCP連接;
3.發(fā)送HTTP請求;
4.服務(wù)器處理請求并返回響應(yīng)結(jié)果;
5.關(guān)閉TCP連接;
6.瀏覽器解析HTML并布局渲染;
==和===的區(qū)別
===比較類型和值,==只比較值。
js在比較的時候如果是 == 會先做類型轉(zhuǎn)換,再判斷值是否相等
null 和 undefined 的區(qū)別
console.log(null==undefined)//true
console.log(null===undefined)//false
Null類型,代表“空值”,代表一個空對象指針,使用typeof運算得到 “object”,所以你可以認(rèn)為它是一個特殊的對象值。
undefined: Undefined類型,當(dāng)一個聲明了一個變量未初始化時,得到的就是undefined。
null:
1作為函數(shù)的參數(shù),表示該函數(shù)的參數(shù)不是對象。
2作為對象原型鏈的終點。
undefined:
1變量被聲明了,但沒有賦值時,就等于undefined。
2調(diào)用函數(shù)時,應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于undefined。
3對象沒有賦值的屬性,該屬性的值為undefined。
4函數(shù)沒有返回值時,默認(rèn)返回undefined。
事件委托/事件代理
事件委托就是利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。
是利用事件冒泡的特性,將本應(yīng)該注冊在子元素上的事件處理程序注冊在了父組件身上,
這樣點擊子元素時,發(fā)現(xiàn)其沒有相應(yīng)事件就會到父元素上尋找做做出響應(yīng),這樣做的優(yōu)勢有:
1、減少dom操作,提高性能
2、隨時都可以添加子元素,子元素也有相應(yīng)的事件處理程序
事件流模型
1. 事件冒泡(fasle/不寫):當(dāng)觸發(fā)一個節(jié)點的事件是,會從當(dāng)前節(jié)點開始,依次觸發(fā)其祖先節(jié)點的同類型事件,直到DOM根節(jié)點。
2. 事件捕獲(true):當(dāng)初發(fā)一個節(jié)點的事件時,會從DOM根節(jié)點開始,依次觸發(fā)其祖先節(jié)點的同類型事件,直到當(dāng)前節(jié)點自身。
3. 什么時候事件冒泡?什么時候事件捕獲?
① 當(dāng)使用addEventListener綁定事件,第三個參數(shù)傳為true時表示事件捕獲;
② 除此之外的所有事件綁定均為事件冒泡。
阻止事件冒泡和默認(rèn)事件
阻止事件冒泡:
① IE10之前,e.cancelBubble = true;
② IE10之后,e.stopPropagation();
阻止默認(rèn)事件:
① IE10之前:e.returnValue = false;
② IE10之后:e.preventDefault();
arguments
arguments 是一個對應(yīng)于傳遞給函數(shù)的參數(shù)的類數(shù)組對象。
arguments對象是所有(非箭頭)函數(shù)中都可用的局部變量。
//轉(zhuǎn)換成真正的數(shù)組
var args = Array.from(arguments)
var args = [...arguments]
數(shù)組的方法
//不改變原數(shù)組的方法
==>array.join():轉(zhuǎn)成字符串,把數(shù)組的所有元素放入一個字符串。元素通過指定的分隔符進(jìn)行分隔,與split()方法相對應(yīng)。
返回值是字符串,不改變原數(shù)組
返回值是排序后的數(shù)組,不改變原數(shù)組
==>array.indexOf(item):找出某個元素在數(shù)組中的索引
返回值是所查詢的數(shù)組元素的下標(biāo),不改變原數(shù)組
==>array.concat(數(shù)組):方法用于合并兩個或多個數(shù)組。此方法不會更改現(xiàn)有數(shù)組,而是返回一個新數(shù)組。
返回值是合并后的新數(shù)組,不改變原數(shù)組
==>array.toString():把數(shù)字轉(zhuǎn)換為字符串/強(qiáng)轉(zhuǎn)字符串調(diào)用該方法的對象不是 Number 時拋出 TypeError 異常。
返回值是字符串,不改變原數(shù)組
==>array.slice(start,end):可從已有的數(shù)組中返回選定的元素
返回值是一個新的數(shù)組,包含從 start 到 end (不包括該元素)的 arrayObject 中的元素,不改變原數(shù)組
==>array.includes(item):用來判斷一個數(shù)組中是否包含一個指定的值,如果包含則返回true,否則返回false;
返回值是boolean值,不改變原數(shù)組
==>array.reduce(function):方法接收一個函數(shù)作為累加器(accumulator),數(shù)組中的每個值(從左到右)開始縮減,最終為一個值。
返回計算結(jié)果
==>arr.filter(function):返回新數(shù)組,不影響原數(shù)組
==>arr.map(function):只是相當(dāng)于把原數(shù)組克隆一份,把克隆的這一份的數(shù)組中的對應(yīng)項改變了,不影響原數(shù)組
==>arr.forEach(function):遍歷數(shù)組中的每一項,沒有返回值,不支持IE
==>Array.isArray(判斷的變量):判斷是否是一個數(shù)組
返回值是boolean值
//改變原數(shù)組的方法
==>array.push(item,item2...):可向數(shù)組的末尾添加一個或多個元素,它直接修改 arrayObject,而不是創(chuàng)建一個新的數(shù)組
返回值是新數(shù)組的長度
==>array.pop():可向數(shù)組的末尾刪除一個元素,它直接修改 arrayObject,而不是創(chuàng)建一個新的數(shù)組
返回值是刪除的元素
==>array.shift():刪除數(shù)組最前面(頭部)的元素
返回值是刪除的那個元素
==>array.unshift(item,item2...):添加一個或多個元素到數(shù)組的頭部
返回值是新數(shù)組的長度
==>array.splice(索引,刪幾個,添加1個,添加2個):通過索引刪除某幾個元素
返回值是被刪除的數(shù)組
==>array.reverse():數(shù)組反轉(zhuǎn)
返回值是相反的數(shù)組(原數(shù)組和返回值是一樣的)
==>array.sort():數(shù)組排序,可以對按字母順序進(jìn)行排序
返回值是排序之后的數(shù)組(原數(shù)組和返回值是一樣的)
orEach/map/filter 方法
for循環(huán):break
forEach:沒有返回值
map:返回一個數(shù)組,適用于需要對數(shù)據(jù)結(jié)構(gòu)進(jìn)行重新整理或加工的數(shù)組
filter:返回一個符合條件的數(shù)組,用來過濾數(shù)據(jù),配合return 使用,只保留數(shù)組中符合條件內(nèi)容
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
total 必需。初始值, 或者計算結(jié)束后的返回值。
currentValue 必需。當(dāng)前元素
currentIndex 可選。當(dāng)前元素的索引
arr 可選。當(dāng)前元素所屬的數(shù)組對象。
initialValue 可選。傳遞給函數(shù)的初始值
對象的方法
Object.assign()
==>通過復(fù)制一個或多個對象來創(chuàng)建一個新的對象。
Object.create()
==>使用指定的原型對象和屬性創(chuàng)建一個新對象。
Object.freeze()
==>凍結(jié)對象:其他代碼不能刪除或更改任何屬性。
Object.keys()
==>返回一個包含所有給定對象自身可枚舉屬性名稱的數(shù)組。
Object.getOwnPropertySymbols()
==>返回一個數(shù)組,它包含了指定對象自身所有的符號屬性。
Object.setPrototypeOf(child,parent)
==>設(shè)置child的對象的原型(即內(nèi)部 [[Prototype]] 屬性)。
Object.defineProperty()
==>給對象添加一個屬性并指定該屬性的配置。
Object.defineProperties()
==>給對象添加多個屬性并分別指定它們的配置。
Object.entries()
==>返回給定對象自身可枚舉屬性的 [key, value] 數(shù)組。
Object.getOwnPropertyDescriptor()
==>返回對象指定的屬性配置。
Object.getOwnPropertyNames()
==>返回一個數(shù)組,它包含了指定對象所有的可枚舉或不可枚舉的屬性名。
Object.getPrototypeOf()
==>返回指定對象的原型對象。
Object.is()
==>比較兩個值是否相同。所有 NaN 值都相等(這與==和===不同)。
Object.isExtensible()
==>判斷對象是否可擴(kuò)展。
Object.isFrozen()
==>判斷對象是否已經(jīng)凍結(jié)。
Object.isSealed()
==>判斷對象是否已經(jīng)密封。
Object.preventExtensions()
==>防止對象的任何擴(kuò)展。
Object.seal()
==>防止其他代碼刪除對象的屬性。
Object.values()
==>返回給定對象自身可枚舉值的數(shù)組。
string 方法
==>split():用于把一個字符串分割成字符串?dāng)?shù)組。與array.join是相反的。字符串變成數(shù)組
返回值是一個數(shù)組
==>indexOf():可返回某個指定的字符串值在字符串中首次出現(xiàn)的位置。對大小寫敏感。
返回值是數(shù)字下標(biāo)
==>concat():用于連接兩個或多個字符串。
返回值是連接后的字符串
==>replace():用于在字符串中用一些字符替換另一些字符,或替換一個與正則表達(dá)式匹配的子串。
返回值是一個新的字符串
==>charAt():可返回指定位置的字符。獲取字符串的某個字符有兩種方法----------------'cat'[1]
返回值是下標(biāo)索引
==>charCodeAt():可返回指定位置的字符的 Unicode 編碼.
返回值是下標(biāo)索引
==>sup():把字符串顯示為上標(biāo)。
==>toUpperCase():把字符串轉(zhuǎn)換為大寫。
==>toLowerCase():把字符串轉(zhuǎn)換為小寫。
==>slice():可提取字符串的某個部分,并以新的字符串返回被提取的部分。包前不包后
==>trim():從字符串的開始和結(jié)尾去除空格。參照部分 ECMAScript 5 標(biāo)準(zhǔn)
==>search():用于檢索字符串中指定的子字符串,或檢索與正則表達(dá)式相匹配的子字符串。
==>repeat(n):復(fù)制n次字符串
==>substr()
==>substring()
==>includes():判斷字符串里是否存在數(shù)據(jù)
返回值是boolean值
設(shè)計模式
一、單例模式
==>確保只有一個實例,并且提供全局訪問
==>var a = {},但是會造成全局污染
二、策略模式
==>策略模式的目的就是將算法的使用與算法的實現(xiàn)分離開來。
==>定義一系列的算法,把它們一個個封裝起來,并且使它們可以相互替換。
三、代理模式
==>圖片懶加載實現(xiàn)的過程就是通過代理模式中的虛擬代理來實現(xiàn)的
==>為其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標(biāo)對象之間起到中介的作用。
四、迭代器模式
==>迭代器模式是指提供一種方法順序訪問一個聚合對象中的各個元素,而又不需要暴露該對象的內(nèi)部表示。
==>for循環(huán)
五、發(fā)布—訂閱模式
==>js事件就是經(jīng)典的
==>發(fā)布-訂閱模式里面包含了三個模塊,發(fā)布者,訂閱者和處理中心。
六、命令模式
==>命令模式中的命令(command)指的是一個執(zhí)行某些特定事情的指令。
==>通過不同的命令做不同的事情,常含有(關(guān)聯(lián))接收者。
==>將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進(jìn)行參數(shù)化
七、組合模式
==>組合模式將對象組合成樹形結(jié)構(gòu),以表示“部分-整體”的層次結(jié)構(gòu)。
==>虛擬dom:將真實的DOM的數(shù)據(jù)抽取出來,以對象的形式模擬樹形結(jié)構(gòu)
八、模板方法模式
==>一種只需使用繼承就可以實現(xiàn)的非常簡單的模式。
==>模板方法由兩部分組成,一是抽象的父類,二是具體實現(xiàn)的子類。通常在抽象父類中封裝了子類的算法框架,包括實現(xiàn)一些公共方法以及封裝子類中所有方法的執(zhí)行順序。
==>ypescript中就有abstract中的抽象類和抽象方法就是使用的模板方法模式
九、裝飾者模式
==>允許向一個現(xiàn)有的對象添加新的功能,同時又不改變其結(jié)構(gòu)。
==>為對象添加新功能;不改變其原有的結(jié)構(gòu)和功能
==>ecorator 是 ES7 的一個新語法;裝飾器語法
十、職責(zé)鏈模式
十一、中介者模式
十三、狀態(tài)模式
十四、適配器模式
十五、外觀模式
十六、享元模式
繼承方式
原型鏈繼承
==>新實例的原型等于父類的實例;(per.prototype = new Person())
借用構(gòu)造函數(shù)繼承(冒充對象)
==>改變this指向;Preson.call(this,'jer')
組合繼承
==>per.prototype =new Person()
==>Preson.call(this,'jer')
原型式繼承
寄生式繼承
寄生組合式繼承
class繼承
==>extends關(guān)鍵字實現(xiàn)super
Ts 的基本了解
TypeScript具有類型系統(tǒng),且是JavaScript的超集。
元組類型:允許表示一個已知元素數(shù)量和類型的數(shù)組,各元素的類型不必相同
==>let arr:[Number,String] = [1,'xxl']
enum類(枚舉):
==>enum flag={success=1,error=-1}
==>let a:flag = flag.success
boolean:let b:Boolean= false
number:let b:Number=1
string:let b:String = 'xxl'
array:定義數(shù)組有三種方式
==>var arr:any[] = [1,2,3]
==>var arr:number[]=[1,2,3]
==>var arr:Array<number>=[1,2,3]
any類型:let b:any = 1
void類型:定義的方法function沒有返回值
null和undefinde:undefinde變量聲明未賦值,
never類型:throw =new Error('錯誤')
瀏覽器的緩存機(jī)制也就是我們說的 HTTP 緩存機(jī)制
強(qiáng)緩存和協(xié)商緩存
==>是瀏覽器在本地磁盤對用戶最近請求過的文檔進(jìn)行存儲,當(dāng)訪問者再次訪問同一頁面時,瀏覽器就可以直接從本地磁盤加載文檔。
TCP 的三次握手和四次揮手?
第一次握手:建立連接時,客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進(jìn)入SYN_SENT狀態(tài),等待服務(wù)器確認(rèn);SYN:同步序列編號(Synchronize Sequence Numbers)。
第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包,此時服務(wù)器進(jìn)入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入ESTABLISHED(TCP連接成功)狀態(tài),完成三次握手。
script 標(biāo)簽后加 async 屬性和 defer 屬性有什么區(qū)別
1.<script src="example.js"></script>
沒有defer或async屬性,瀏覽器會立即加載并執(zhí)行相應(yīng)的腳本。也就是說在渲染script標(biāo)簽之后的文檔之前,不等待后續(xù)加載的文檔元素,讀到就開始加載和執(zhí)行,此舉會阻塞后續(xù)文檔的加載;
2.<script async src="example.js"></script>
有了async屬性,表示后續(xù)文檔的加載和渲染與js腳本的加載和執(zhí)行是并行進(jìn)行的,即異步執(zhí)行;
3.<script defer src="example.js"></script>
有了defer屬性,加載后續(xù)文檔的過程和js腳本的加載(此時僅加載不執(zhí)行)是并行進(jìn)行的(異步),js腳本的執(zhí)行需要等到文檔所有元素解析完成之后,DOMContentLoaded事件觸發(fā)執(zhí)行之前。
AMD、CMD、ES6、CommonJS 的區(qū)別
js規(guī)范
1. 第一種是 CommonJS 方案,它通過 require 來引入模塊,通過 module.exports 定義模塊的輸出接口。這種模塊加載方案是服務(wù)器端的解決方案,它是以同步的方式來引入模塊的,因為在服務(wù)端文件都存儲在本地磁盤,所以讀取非???,所以以同步的方式加載沒有問題。但如果是在瀏覽器端,由于模塊的加載是使用網(wǎng)絡(luò)請求,因此使用異步加載的方式更加合適。
2. 第二種是 AMD 方案,這種方案采用異步加載的方式來加載模塊,模塊的加載不影響后面語句的執(zhí)行,所有依賴這個模塊的語句都定義在一個回調(diào)函數(shù)里,等到加載完成后再執(zhí)行回調(diào)函數(shù)。require.js 實現(xiàn)了 AMD 規(guī)范。
3. 第三種是 CMD 方案,這種方案和 AMD 方案都是為了解決異步模塊加載的問題,sea.js 實現(xiàn)了 CMD 規(guī)范。它和require.js的區(qū)別在于模塊定義時對依賴的處理不同和對依賴模塊的執(zhí)行時機(jī)的處理不同。
4. 第四種方案是 ES6 提出的方案,使用 import 和 export 的形式來導(dǎo)入導(dǎo)出模塊。
==>1.commonjs輸出的,是一個值的拷貝,而es6輸出的是值的引用;
==>2.commonjs是運行時加載,es6是編譯時輸出接口;
深拷貝和淺拷貝(手寫代碼)
==>淺拷貝是拷貝一層,對象級別的就拷貝引用;
==>深拷貝是拷貝多層,每一級別的數(shù)據(jù)都會拷貝出來;
數(shù)組去重(手寫代碼)
==>Array.from(new Set(arr))
==>filter 加 indexOf 方法
==>forEach 加 incluse 方法
防抖和節(jié)流(手寫代碼)
==>防抖就是閉包加定時器
==>節(jié)流就是使用時間戳來實現(xiàn)的
jsonp(手寫代碼)
==> JSONP 核心原理:script 標(biāo)簽不受同源策略約束,所以可以用來進(jìn)行跨域請求,優(yōu)點是兼容性好,但是只能用于 GET 請求;
==>img 標(biāo)簽,link 標(biāo)簽,script 標(biāo)簽
冒泡排序算法(手寫代碼)
斐波那契數(shù)列(手寫代碼)
如何實現(xiàn) new 運算符(手寫代碼)
函數(shù)柯里化(手寫代碼)
偏函數(shù)(手寫代碼)
原生 js 實現(xiàn) ajax(手寫代碼)
多維數(shù)組怎么變成一個一維數(shù)組(手寫代碼)
數(shù)組扁平化(手寫代碼)
封裝 axios(手寫代碼)
圖片懶加載的實現(xiàn)原理(手寫代碼)