JavaScript

js基礎(chǔ)

1.javaScript的數(shù)據(jù)類型有什么

基本數(shù)據(jù)類型:Undefined、Null、Boolean、Number、String

復(fù)雜數(shù)據(jù)類型:object,array,function

區(qū)別:基本數(shù)據(jù)類型把數(shù)據(jù)名和值直接存儲(chǔ)在棧當(dāng)中;復(fù)雜數(shù)據(jù)類型在棧中存儲(chǔ)數(shù)據(jù)名和一個(gè)堆的地址,在堆中存儲(chǔ)屬性及值,訪問時(shí)先從棧中獲取地址,再到堆中拿出相應(yīng)的值

2.檢測數(shù)據(jù)類型有什么方法

typeof

typeof xxx得到的值有以下幾種類型:undefined boolean number string object function、symbol ,比較簡單,不再一一演示了。

這里需要注意的有三點(diǎn):

typeof null結(jié)果是object ,實(shí)際這是typeof的一個(gè)bug,null是原始值,非引用類型

typeof [1, 2]結(jié)果是object,結(jié)果中沒有array這一項(xiàng),引用類型除了function其他的全部都是object

typeof Symbol() 用typeof獲取symbol類型的值得到的是symbol,這是 ES6 新增的知識(shí)點(diǎn)

instanceof

用于實(shí)例和構(gòu)造函數(shù)的對應(yīng)。例如判斷一個(gè)變量是否是數(shù)組,使用typeof無法判斷,但可以使用[1, 2] instanceof Array來判斷。因?yàn)?,[1, 2]是數(shù)組,它的構(gòu)造函數(shù)就是Array。

同理:

functionFoo(name) {

????this.name = name

?}

var foo =newFoo('bar’)

console.log(foo instanceof Foo) // true


3.介紹js有哪些內(nèi)置對象?

Object 是 JavaScript 中所有對象的父對象?

數(shù)據(jù)封裝類對象:Object、Array、Boolean、Number 和 String?

其他對象:Function、Arguments、Math、Date、RegEx、Error

4.如何區(qū)分?jǐn)?shù)組和對象?

(1)從原型入手,Array.prototype.isPrototypeOf(obj); ?利用isPrototypeOf()方法,判定Array是不是在obj的原型鏈中,如果是,則返回true,否則false。Array.prototype.isPrototype([]) //true?

(2)也可以從構(gòu)造函數(shù)入手,利用對向的constructor屬性?

(3)根據(jù)對象的class屬性(類屬性),跨原型鏈調(diào)用toString()方法。Object.prototype.toString.call(Window);?

(4)Array.isArray()方法。

5.null,undefined 的區(qū)別?

null ? ? ? ?表示一個(gè)對象被定義了,值為“空值”;?

undefined ? 表示不存在這個(gè)值。?


typeof undefined ? ? ? ? ? ? ? ? ? ? ?//"undefined"?

undefined :是一個(gè)表示"無"的原始值或者說表示"缺少值",就是此處應(yīng)該有一個(gè)值,但是還沒有定義。當(dāng)嘗試讀取時(shí)會(huì)返回 undefined;?

例如變量被聲明了,但沒有賦值時(shí),就等于undefined

typeof null ? ? ? ?//"object"?

null : 是一個(gè)對象(空對象, 沒有任何屬性和方法);?

例如作為函數(shù)的參數(shù),表示該函數(shù)的參數(shù)不是對象;

注意:

在驗(yàn)證null時(shí),一定要使用 === ,因?yàn)?== 無法分別 null 和 undefined?

undefined表示"缺少值",就是此處應(yīng)該有一個(gè)值,但是還沒有定義。典型用法是:?

1)變量被聲明了,但沒有賦值時(shí),就等于undefined。?

2) 調(diào)用函數(shù)時(shí),應(yīng)該提供的參數(shù)沒有提供,該參數(shù)等于undefined。?

3)對象沒有賦值的屬性,該屬性的值為undefined。?

4)函數(shù)沒有返回值時(shí),默認(rèn)返回undefined。

null表示"沒有對象",即該處不應(yīng)該有值。

典型用法是:?

1) 作為函數(shù)的參數(shù),表示該函數(shù)的參數(shù)不是對象。?

2) 作為對象原型鏈的終點(diǎn)。

6.聲明變量和聲明函數(shù)的提升有什么區(qū)別?

(1) 變量聲明提升:變量申明在進(jìn)入執(zhí)行上下文就完成了。?

只要變量在代碼中進(jìn)行了聲明,無論它在哪個(gè)位置上進(jìn)行聲明, js引擎都會(huì)將它的聲明放在范圍作用域的頂部;?

(2) 函數(shù)聲明提升:執(zhí)行代碼之前會(huì)先讀取函數(shù)聲明,意味著可以把函數(shù)申明放在調(diào)用它的語句后面。?

只要函數(shù)在代碼中進(jìn)行了聲明,無論它在哪個(gè)位置上進(jìn)行聲明, js引擎都會(huì)將它的聲明放在范圍作用域的頂部;?

(3) 變量or函數(shù)聲明:函數(shù)聲明會(huì)覆蓋變量聲明,但不會(huì)覆蓋變量賦值。?

同一個(gè)名稱標(biāo)識(shí)a,即有變量聲明var a,又有函數(shù)聲明function a() {},不管二者聲明的順序,函數(shù)聲明會(huì)覆蓋變量聲明,也就是說,此時(shí)a的值是聲明的函數(shù)function a() {}。注意:如果在變量聲明的同時(shí)初始化a,或是之后對a進(jìn)行賦值,此時(shí)a的值變量的值。

var a;

var c = 1;

a = 1;

function a() {

????????return true;

}

console.log(a);

原型,原型鏈

1.JavaScript原型,原型鏈 ? 有什么特點(diǎn)?

原型

每個(gè)對象都會(huì)在其內(nèi)部初始化一個(gè)屬性,就是prototype(原型)?

使用hasOwnProperty() 可以判斷這個(gè)屬性是不是對象本身的屬性

問題:Javascript中,有一個(gè)函數(shù),執(zhí)行時(shí)對象查找時(shí),永遠(yuǎn)不會(huì)去查找原型,這個(gè)函數(shù)是?

hasOwnProperty?

javaScript中hasOwnProperty函數(shù)方法是返回一個(gè)布爾值,指出一個(gè)對象是否具有指定名稱的屬性。此方法無法檢查該對象的原型鏈中是否具有該屬性;該屬性必須是對象本身的一個(gè)成員。

使用方法:?

object.hasOwnProperty(proName)?

其中參數(shù)object是必選項(xiàng)。一個(gè)對象的實(shí)例。?

proName是必選項(xiàng)。一個(gè)屬性名稱的字符串值。

如果 object 具有指定名稱的屬性,那么JavaScript中hasOwnProperty函數(shù)方法返回 true,反之則返回 false。

原型鏈

當(dāng)我們在訪問一個(gè)對象的屬性時(shí),如果這個(gè)對象內(nèi)部不存在這個(gè)屬性,那么他就會(huì)去prototype里找這個(gè)屬性,這個(gè)prototype又會(huì)有自己的prototype,于是就這樣一直找下去,找到Object.__proto__為止,找不到就返回unde也就是我們平時(shí)所說的原型鏈的概念。?

關(guān)系:instance.constructor.prototype = instance.__proto__?

特點(diǎn):?

JavaScript對象是通過引用來傳遞的,我們創(chuàng)建的每個(gè)新對象實(shí)體中并沒有一份屬于自己的原型副本。當(dāng)我們修改原型時(shí),與之相關(guān)的對象也會(huì)繼承這一改變。?

當(dāng)我們需要一個(gè)屬性的時(shí),Javascript引擎會(huì)先看當(dāng)前對象中是否有這個(gè)屬性, 如果沒有的話,就會(huì)查找他的Prototype對象是否有這個(gè)屬性,如此遞推下去,一直檢索到 Object 內(nèi)建對象。

所有的引用類型(數(shù)組、對象、函數(shù)),都具有對象特性,即可自由擴(kuò)展屬性(null除外)?

所有的引用類型(數(shù)組、對象、函數(shù)),都有一個(gè)__proto__屬性,屬性值是一個(gè)普通的對象?

所有的函數(shù),都有一個(gè)prototype屬性,屬性值也是一個(gè)普通的對象?

所有的引用類型(數(shù)組、對象、函數(shù)),__proto__屬性值指向它的構(gòu)造函數(shù)的prototype屬性值

原型鏈中的this

所有從原型或更高級原型中得到、執(zhí)行的方法,其中的this在執(zhí)行時(shí),就指向了當(dāng)前這個(gè)觸發(fā)事件執(zhí)行的對象。

閉包

閉包的形成與變量的作用域以及變量的生存周期有密切的關(guān)系

1.變量的作用域

在js中我們把作用域分為全局作用域和局部作用域,全局作用域就是window,在沒有塊級作用域概念的時(shí)候,每一個(gè)函數(shù)都是一個(gè)局部作用域。

其實(shí)變量的作用域,就說指變量的有效范圍。我們最長說的就是在函數(shù)中聲明的變量作用域。

當(dāng)在函數(shù)中聲明一個(gè)變量的時(shí)候,如果改變量沒有用var關(guān)鍵字去定義那么該變量就是一個(gè)全局變量,但是這樣做最容易造成命名沖突。

另一種情況就是使用var聲明的變量,這時(shí)候的變量就是局部變量,只有在該函數(shù)內(nèi)部可以訪問,在函數(shù)外面是訪問不到的

在javascript中,函數(shù)可以用來創(chuàng)造函數(shù)作用域。在函數(shù)中搜索變量的時(shí)候,如果該函數(shù)當(dāng)中沒有這個(gè)變量,那么這次搜索過程會(huì)隨著代碼執(zhí)行環(huán)境創(chuàng)建的作用域鏈往外層逐層搜索,一直搜索到window對象為止,找不到就會(huì)拋出一個(gè)為定義的錯(cuò)誤。而這種從內(nèi)到外逐層查找的關(guān)系在js中我們稱為作用域鏈

2.變量的生存周期

除了變量作用域之外,另外一個(gè)跟閉包有關(guān)的概念就是變量的生存周期,對于全局變量來說,全局變量的生存周期是永久的,除非我們主動(dòng)銷毀這個(gè)全局變量,而對于函數(shù)內(nèi)部的使用var聲明的變量來說,當(dāng)退出函數(shù)是,這些變量就會(huì)隨著函數(shù)的結(jié)束而銷毀。

3.閉包的形成

Javascript允許使用內(nèi)部函數(shù),可以將函數(shù)定義和函數(shù)表達(dá)式放在另一個(gè)函數(shù)的函數(shù)體內(nèi)。而且,內(nèi)部函數(shù)可以訪問它所在的外部函數(shù)聲明的局部變量、參數(shù)以及聲明的其他內(nèi)部函數(shù)。當(dāng)其中一個(gè)這樣的內(nèi)部函數(shù)在包含它們的外部函數(shù)之外被調(diào)用時(shí),就會(huì)形成閉包。常見的閉包寫法就是簡單的函數(shù)套函數(shù),通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量,利用閉包可以突破作用域鏈,將函數(shù)內(nèi)部的變量和方法傳遞到外部,延續(xù)變量的生命。使用閉包可以減少全局環(huán)境的污染,也可用延續(xù)變量的生命。

4.閉包的適用場景

閉包的適用場景非常廣泛,首先從閉包的優(yōu)點(diǎn)出發(fā)就是:?

減少全局環(huán)境的污染生成獨(dú)立的運(yùn)行環(huán)境

模塊化就是利用這個(gè)特點(diǎn)對不同的模塊都有自己獨(dú)立的運(yùn)行環(huán)境,不會(huì)和全局沖突,模塊和模塊之間通過拋出的接口進(jìn)行依賴使用?

以及像我們常用的jquery類庫(避免和全局沖突使用閉包實(shí)現(xiàn)自己獨(dú)立的環(huán)境)

可以通過返回其他函數(shù)的方式突破作用域鏈

可以利用這個(gè)功能做一些值的緩存工作,例如常見的設(shè)計(jì)模式(單例模式),以及現(xiàn)在比較火的框架vue中的計(jì)算屬性

其實(shí)當(dāng)遇到以下場景的時(shí)候都可以使用閉包?

1) 維護(hù)函數(shù)內(nèi)的變量安全,避免全局變量的污染。?

2) 維持一個(gè)變量不被回收。?

3) 封裝模塊

5.閉包的缺點(diǎn)

由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大。所以在閉包不用之后,將不使用的局部變量刪除,使其被回收。在IE中可能導(dǎo)致內(nèi)存泄露,即無法回收駐留在內(nèi)存中的元素,這時(shí)候需要手動(dòng)釋放。

6.內(nèi)存泄露

內(nèi)存泄漏指一塊被分配的內(nèi)存既不能使用,又不能回收,直到瀏覽器進(jìn)程結(jié)束。

出現(xiàn)原因:

1) 循環(huán)引用:含有DOM對象的循環(huán)引用將導(dǎo)致大部分當(dāng)前主流瀏覽器內(nèi)存泄露。循環(huán) 引用,簡單來說假如a引用了b,b又引用了a,a和b就構(gòu)成了循環(huán)引用。?

2) JS閉包:閉包,函數(shù)返回了內(nèi)部函數(shù)還可以繼續(xù)訪問外部方法中定義的私有變量。?

3) Dom泄露,當(dāng)原有的DOM被移除時(shí),子結(jié)點(diǎn)引用沒有被移除則無法回收。

7.JavaScript垃圾回收機(jī)制

Javascript中,如果一個(gè)對象不再被引用,那么這個(gè)對象就會(huì)被GC(garbage collection)回收。如果兩個(gè)對象互相引用,而不再被第3者所引用,那么這兩個(gè)互相引用的對象也會(huì)被回收。垃圾回收不是時(shí)時(shí)的,因?yàn)槠溟_銷比較大,所以垃圾回收器會(huì)按照固定的時(shí)間間隔周期性的執(zhí)行。

函數(shù)a被b引用,b又被a外的c引用,這就是為什么函數(shù)a執(zhí)行后不會(huì)被回收的原因。

8.垃圾回收的兩個(gè)方法:

標(biāo)記清除法:

1) 垃圾回收機(jī)制給存儲(chǔ)在內(nèi)存中的所有變量加上標(biāo)記,然后去掉環(huán)境中的變量以及被環(huán)境中變量所引用的變量(閉包)。?

2) 操作1之后內(nèi)存中仍存在標(biāo)記的變量就是要?jiǎng)h除的變量,垃圾回收機(jī)制將這些帶有標(biāo)記的變量回收。

引用計(jì)數(shù)法:

1) 垃圾回收機(jī)制給一個(gè)變量一個(gè)引用次數(shù),當(dāng)聲明了一個(gè)變量并將一個(gè)引用類型賦值給該變量的時(shí)候這個(gè)值的引用次數(shù)就加1。?

2) 當(dāng)該變量的值變成了另外一個(gè)值,則這個(gè)值得引用次數(shù)減1。?

3) 當(dāng)這個(gè)值的引用次數(shù)變?yōu)?的時(shí)候,說明沒有變量在使用,垃圾回收機(jī)制會(huì)在運(yùn)行的時(shí)候清理掉引用次數(shù)為0的值占用的空間。

JS運(yùn)行機(jī)制

JavaScript引擎是單線程運(yùn)行的,瀏覽器無論在什么時(shí)候都只且只有一個(gè)線程在運(yùn)行JavaScript程序.瀏覽器的內(nèi)核是多線程的,它們在內(nèi)核制控下相互配合以保持同步,一個(gè)瀏覽器至少實(shí)現(xiàn)三個(gè)常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發(fā)線程。這些異步線程都會(huì)產(chǎn)生不同的異步的事件.

1) javascript引擎是基于事件驅(qū)動(dòng)單線程執(zhí)行的,JS引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理,瀏覽器無論什么時(shí)候都只有一個(gè)JS線程在運(yùn)行JS程序。

2) GUI渲染線程負(fù)責(zé)渲染瀏覽器界面,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(reflow)時(shí),該線程就會(huì)執(zhí)行。但需要注意 GUI渲染線程與JS引擎是互斥的,當(dāng)JS引擎執(zhí)行時(shí)GUI線程會(huì)被掛起,GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JS引擎空閑時(shí)立即被執(zhí)行。

3) 事件觸發(fā)線程,當(dāng)一個(gè)事件被觸發(fā)時(shí)該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當(dāng)前執(zhí)行的代碼塊如setTimeOut、也可來自瀏覽器內(nèi)核的其他線程如鼠標(biāo)點(diǎn)擊、AJAX異步請求等,但由于JS的單線程關(guān)系所有這些事件都得排隊(duì)等待JS引擎處理。(當(dāng)線程中沒有執(zhí)行任何同步代碼的前提下才會(huì)執(zhí)行異步代碼)

當(dāng)程序啟動(dòng)時(shí), 一個(gè)進(jìn)程被創(chuàng)建,同時(shí)也運(yùn)行一個(gè)線程, 即為主線程,js的運(yùn)行機(jī)制為單線程

程序中跑兩個(gè)線程,一個(gè)負(fù)責(zé)程序本身的運(yùn)行,作為主線程; 另一個(gè)負(fù)責(zé)主線程與其他線程的的通信,被稱為“Event Loop 線程" 。每當(dāng)遇到異步任務(wù),交給 EventLoop 線程,然后自己往后運(yùn)行,等到主線程運(yùn)行完后,再去 EventLoop 線程拿結(jié)果。

1)所有任務(wù)都在主線程上執(zhí)行,形成一個(gè)執(zhí)行棧(execution context stack)。

2)主線程之外,還存在一個(gè)"任務(wù)隊(duì)列"(task queue)。系統(tǒng)把異步任務(wù)放到"任務(wù)隊(duì)列"之中,然后繼續(xù)執(zhí)行后續(xù)的任務(wù)。

3)一旦"執(zhí)行棧"中的所有任務(wù)執(zhí)行完畢,系統(tǒng)就會(huì)讀取"任務(wù)隊(duì)列"。如果這個(gè)時(shí)候,異步任務(wù)已經(jīng)結(jié)束了等待狀態(tài),就會(huì)從"任務(wù)隊(duì)列"進(jìn)入執(zhí)行棧,恢復(fù)執(zhí)行。

4)主線程不斷重復(fù)上面的第三步。

"回調(diào)函數(shù)"(callback),就是那些會(huì)被主線程掛起來的代碼。異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)異步任務(wù)從"任務(wù)隊(duì)列"回到執(zhí)行棧,回調(diào)函數(shù)就會(huì)執(zhí)行。"任務(wù)隊(duì)列"是一個(gè)先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),排在前面的事件,優(yōu)先返回主線程。主線程的讀取過程基本上是自動(dòng)的,只要執(zhí)行棧一清空,"任務(wù)隊(duì)列"上第一位的事件就自動(dòng)返回主線程。

主線程從"任務(wù)隊(duì)列"中讀取事件,這個(gè)過程是循環(huán)不斷的,所以整個(gè)的這種運(yùn)行機(jī)制又稱為Event Loop。

從主線程的角度看,一個(gè)異步過程包括下面兩個(gè)要素:

發(fā)起函數(shù)(或叫注冊函數(shù))A

回調(diào)函數(shù)callbackFn

它們都是在主線程上調(diào)用的,其中注冊函數(shù)用來發(fā)起異步過程,回調(diào)函數(shù)用來處理結(jié)果。

異步進(jìn)程有:

類似onclick等,由瀏覽器內(nèi)核的DOM binding模塊處理,事件觸發(fā)時(shí),回調(diào)函數(shù)添加到任務(wù)隊(duì)列中;

setTimeout等,由瀏覽器內(nèi)核的Timer模塊處理,時(shí)間到達(dá)時(shí),回調(diào)函數(shù)添加到任務(wù)隊(duì)列中;

Ajax,由瀏覽器內(nèi)核的Network模塊處理,網(wǎng)絡(luò)請求返回后,添加到任務(wù)隊(duì)列中。

例如setTimeout(fn, 1000),其中的setTimeout就是異步過程的發(fā)起函數(shù),fn是回調(diào)函數(shù)。用一句話概括:工作線程將消息放到消息隊(duì)列,主線程通過事件循環(huán)過程去取消息。

消息隊(duì)列:消息隊(duì)列是一個(gè)先進(jìn)先出的隊(duì)列,它里面存放著各種消息。

事件循環(huán):事件循環(huán)是指主線程重復(fù)從消息隊(duì)列中取消息、執(zhí)行的過程。

流程如下:

1) 主線程讀取js代碼, 形成相應(yīng)的堆和執(zhí)行棧, 執(zhí)行同步任務(wù)

2) 當(dāng)主線程遇到異步任務(wù),,指定給異步進(jìn)程處理, 同時(shí)繼續(xù)執(zhí)行同步任務(wù)

3) 當(dāng)異步進(jìn)程處理完畢后, 將相應(yīng)的異步任務(wù)推入到任務(wù)隊(duì)列首部

4) 主線程任務(wù)處理完畢后,,查詢?nèi)蝿?wù)隊(duì)列,則取出一個(gè)任務(wù)隊(duì)列推入到主線程的執(zhí)行棧

5) 重復(fù)執(zhí)行第2、3、4步,這就稱為事件循環(huán)

JS-Web-API 知識(shí)點(diǎn)與高頻考題解析

BOM

BOM(瀏覽器對象模型)是瀏覽器本身的一些信息的設(shè)置和獲取,例如獲取瀏覽器的寬度、高度,設(shè)置讓瀏覽器跳轉(zhuǎn)到哪個(gè)地址。?

navigator:?獲取瀏覽器特性(即俗稱的UA)然后識(shí)別客戶端?

location:?獲取網(wǎng)址、協(xié)議、path、參數(shù)、hash 等?

history: 操作瀏覽器的歷史紀(jì)錄,(前進(jìn),后退等功能)

1.什么是window對象? 什么是document對象?

window:它是一個(gè)頂層對象,而不是另一個(gè)對象的屬性,即瀏覽器的窗口。?

document:代表整個(gè)HTML 文檔,可用來訪問頁面中的所有元素?

Window 對象表示當(dāng)前瀏覽器的窗口,是JavaScript的頂級對象。我們創(chuàng)建的所有對象、函數(shù)、變量都是 Window 對象的成員。?

Window 對象的方法和屬性是在全局范圍內(nèi)有效的。?

Document 對象是 HTML 文檔的根節(jié)點(diǎn)與所有其他節(jié)點(diǎn)(元素節(jié)點(diǎn),文本節(jié)點(diǎn),屬性節(jié)點(diǎn), 注釋節(jié)點(diǎn))?

Document 對象使我們可以通過腳本對 HTML 頁面中的所有元素進(jìn)行訪問?

Document 對象是 Window 對象的一部分,可通過 window.document 屬性對其進(jìn)行訪問

2.事件是?IE與火狐的事件機(jī)制有什么區(qū)別? 如何阻止冒泡?

1) 我們在網(wǎng)頁中的某個(gè)操作(有的操作對應(yīng)多個(gè)事件)。例如:當(dāng)我們點(diǎn)擊一個(gè)按鈕就會(huì)產(chǎn)生一個(gè)事件。是可以被 JavaScript 偵測到的行為。?

2) 事件處理機(jī)制:IE是事件冒泡、Firefox同時(shí)支持兩種事件模型,也就是:捕獲型事件和冒泡型事件;?

3) ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)

3.解釋一下事件代理

事件代理的原理其實(shí)就和作用域鏈的原理差不多,但是事件代理是利用事件的冒泡原理來實(shí)現(xiàn)的,事件代理就是通過給祖先元素添加事件,通過事件目標(biāo)對象開始向上查找找到匹配的子節(jié)點(diǎn)為止,如果找不到則到綁定事件的那個(gè)祖先元素為止,找到了就觸發(fā)事件,并且可以通過js中call和apply來改變觸發(fā)事件函數(shù)中的this為當(dāng)前綁定節(jié)點(diǎn),也是通過一層一層逐層向上的方式進(jìn)行匹配查找而觸發(fā)對應(yīng)事件,好處就是可以使后添加的dom元素也同樣有之前存在元素的事件,jquery中可以使用on,delegate,live實(shí)現(xiàn)的,不過在jquery1.7版本以后吧live給廢除了,原因就是live綁定事件的祖先元素是整個(gè)html頁面的根節(jié)點(diǎn),所以性能消耗比較大,在后邊的版本中給刪除了,使用on,delegate代替

優(yōu)點(diǎn):

使代碼簡潔?

減少瀏覽器的內(nèi)存占用

缺點(diǎn):

使用不當(dāng)會(huì)造成事件在不應(yīng)該觸發(fā)時(shí)觸發(fā)

function? bindEvent (elem, type, selector, fn) {

? ??????// 這樣處理,可接收兩種調(diào)用方式?bindEvent(div1, 'click', 'a', function () {...}) 和bindEvent(div1, 'click', function () {...}) 這兩種?

? ??????if(fn ==null) {

? ???????????fn = selector

? ???????????selector =null

? ??????}

? ??????// 綁定事件?

? ??????elem.addEventListener(type,function(e){

? ??????????var target

? ??????????if(selector) {

? ??????????????// 有 selector 說明需要做事件代理

? ???????????????// 獲取觸發(fā)時(shí)間的元素,即?

? ??????????????e.target target = e.target

? ??????????????// 看是否符合 selector 這個(gè)條件?

? ??????????????if(target.matches(selector)) {

? ???????????????????fn.call(target, e)

? ???????????????}

? ??? ? ? ???}else{

? ??????????????// 無 selector ,說明不需要事件代理

? ???????????????fn(e)

? ???????????}

? ???????})

? ???}

? ??// 使用代理,bindEvent 多一個(gè) 'a' 參數(shù)

?? ??var div1 =document.getElementById('div1')?

? ??bindEvent(div1,'click','a',function(e){

? ??????console.log(this.innerHTML)?

? ??})

? ??// 不使用代理?

? ??var a =document.getElementById('a1')?

? ??bindEvent(div1,'click',function(e){

? ??????console.log(a.innerHTML)

? ???})

4.offsetWidth/offsetHeight,clientWidth/clientHeight與scrollWidth/scrollHeight的區(qū)別

offsetWidth/offsetHeight返回值包含content + padding + border,效果與e.getBoundingClientRect()相同?

clientWidth/clientHeight返回值只包含content + padding,如果有滾動(dòng)條,也不包含滾動(dòng)條?

scrollWidth/scrollHeight返回值包含content + padding + 溢出內(nèi)容的尺寸

5.focus/blur與focusin/focusout的區(qū)別與聯(lián)系

focus/blur不冒泡,focusin/focusout冒泡?

focus/blur兼容性好,focusin/focusout在除FireFox外的瀏覽器下都保持良好兼容性,如需使用事件托管,可考慮在FireFox下使用事件捕獲elem.addEventListener('focus', handler, true)

可獲得焦點(diǎn)的元素:

window?

鏈接被點(diǎn)擊或鍵盤操作?

表單空間被點(diǎn)擊或鍵盤操作?

設(shè)置tabindex屬性的元素被點(diǎn)擊或鍵盤操作

6.mouseover/mouseout與mouseenter/mouseleave的區(qū)別與聯(lián)系

mouseover/mouseout是標(biāo)準(zhǔn)事件,所有瀏覽器都支持;mouseenter/mouseleave是IE5.5引入的特有事件后來被DOM3標(biāo)準(zhǔn)采納,現(xiàn)代標(biāo)準(zhǔn)瀏覽器也支持?

mouseover/mouseout是冒泡事件;mouseenter/mouseleave不冒泡。需要為多個(gè)元素監(jiān)聽鼠標(biāo)移入/出事件時(shí),推薦mouseover/mouseout托管,提高性能?

標(biāo)準(zhǔn)事件模型中event.target表示發(fā)生移入/出的元素,vent.relatedTarget對應(yīng)移出/如元素;在老IE中event.srcElement表示發(fā)生移入/出的元素,event.toElement表示移出的目標(biāo)元素,event.fromElement表示移入時(shí)的來源元素

7.介紹DOM0,DOM2,DOM3事件處理方式區(qū)別

DOM0級事件處理方式:


btn.onclick = func;?

btn.onclick = null;

DOM2級事件處理方式:


btn.addEventListener('click',func,false);

btn.removeEventListener('click',func,false);

btn.attachEvent("onclick",func);

btn.detachEvent("onclick",func);

DOM3級事件處理方式:

eventUtil.addListener(input, "textInput", func);?

eventUtil 是自定義對象,textInput 是DOM3級事件

8.事件的三個(gè)階段

捕獲、目標(biāo)、冒泡

js的冒泡(Bubbling Event)和捕獲(Capture Event)的區(qū)別

冒泡型事件:事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對象)的順序觸發(fā)。?

捕獲型事件(event capturing):事件從最不精確的對象(document 對象)開始觸發(fā),然后到最精確(也可以在窗口級別捕獲事件,不過必須由開發(fā)人員特別指定)。?

DOM事件流:同時(shí)支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流會(huì)觸及DOM中的所有對象,從document對象開始,也在document對象結(jié)束。

事件捕獲

當(dāng)你使用事件捕獲時(shí),父級元素先觸發(fā),子級元素后觸發(fā),即div先觸發(fā),p后觸發(fā)。

事件冒泡

當(dāng)你使用事件冒泡時(shí),子級元素先觸發(fā),父級元素后觸發(fā),即p先觸發(fā),div后觸發(fā)。

阻止冒泡

在W3c中,使用stopPropagation()方法

在IE下設(shè)置cancelBubble = true;

在捕獲的過程中stopPropagation();后,后面的冒泡過程也不會(huì)發(fā)生了。

阻止捕獲

阻止事件的默認(rèn)行為,例如click?后的跳轉(zhuǎn)

在W3c中,使用preventDefault()方法;

在IE下設(shè)置window.event.returnValue = false;

9.介紹事件“捕獲”和“冒泡”執(zhí)行順序和事件的執(zhí)行次數(shù)?

按照W3C標(biāo)準(zhǔn)的事件:首是進(jìn)入捕獲階段,直到達(dá)到目標(biāo)元素,再進(jìn)入冒泡階段?

事件執(zhí)行次數(shù)(DOM2-addEventListener):元素上綁定事件的個(gè)數(shù)?

注意1:前提是事件被確實(shí)觸發(fā)?

注意2:事件綁定幾次就算幾個(gè)事件,即使類型和功能完全一樣也不會(huì)“覆蓋”?

事件執(zhí)行順序:判斷的關(guān)鍵是否目標(biāo)元素?

非目標(biāo)元素:根據(jù)W3C的標(biāo)準(zhǔn)執(zhí)行:捕獲->目標(biāo)元素->冒泡(不依據(jù)事件綁定順序)?

目標(biāo)元素:依據(jù)事件綁定順序:先綁定的事件先執(zhí)行(不依據(jù)捕獲冒泡標(biāo)準(zhǔn))?

最終順序:父元素捕獲->目標(biāo)元素事件1->目標(biāo)元素事件2->子元素捕獲->子元素冒泡->父元素冒泡?

注意:子元素事件執(zhí)行前提 事件確實(shí)“落”到子元素布局區(qū)域上,而不是簡單的具有嵌套關(guān)系?

在一個(gè)DOM上同時(shí)綁定兩個(gè)點(diǎn)擊事件:一個(gè)用捕獲,一個(gè)用冒泡。事件會(huì)執(zhí)行幾次,先執(zhí)行冒泡還是捕獲?

該DOM上的事件如果被觸發(fā),會(huì)執(zhí)行兩次(執(zhí)行次數(shù)等于綁定次數(shù))?

如果該DOM是目標(biāo)元素,則按事件綁定順序執(zhí)行,不區(qū)分冒泡/捕獲?

如果該DOM是處于事件流中的非目標(biāo)元素,則先執(zhí)行捕獲,后執(zhí)行冒泡

10.window.onload 和 document.DOMContentLoaded ?(注:$(document).ready()) ?的區(qū)別?

一般情況下,DOMContentLoaded事件要在window.onload之前執(zhí)行,當(dāng)DOM樹構(gòu)建完成的時(shí)候就會(huì)執(zhí)行DOMContentLoaded事件,而window.onload是在頁面載入完成的時(shí)候,才執(zhí)行,這其中包括圖片等元素。大多數(shù)時(shí)候我們只是想在DOM樹構(gòu)建完成后,綁定事件到元素,我們并不需要圖片元素,加上有時(shí)候加載外域圖片的速度非常緩慢。

DOM

講 DOM 先從 HTML 講起,講 HTML 先從 XML 講起。XML 是一種可擴(kuò)展的標(biāo)記語言,所謂可擴(kuò)展就是它可以描述任何結(jié)構(gòu)化的數(shù)據(jù),它是一棵樹!

1.documen.write和 innerHTML的區(qū)別

document.write只能重繪整個(gè)頁面?

innerHTML可以重繪頁面的一部分

2.DOM操作——怎樣添加、移除、移動(dòng)、復(fù)制、創(chuàng)建和查找節(jié)點(diǎn)?

1)創(chuàng)建新節(jié)點(diǎn)

createDocumentFragment()//創(chuàng)建一個(gè)DOM片段 createElement()//創(chuàng)建一個(gè)具體的元素 createTextNode()//創(chuàng)建一個(gè)文本節(jié)點(diǎn)

2)添加、移除、替換、插入

appendChild()removeChild()replaceChild()insertBefore()//在已有的子節(jié)點(diǎn)前插入一個(gè)新的子節(jié)點(diǎn)

3)查找

getElementsByTagName()//通過標(biāo)簽名稱 getElementsByName()//通過元素的Name屬性的值(IE容錯(cuò)能力較強(qiáng),會(huì)得到一個(gè)數(shù)組,其中包括id等于name值的) getElementById()//通過元素Id,唯一性

3.attribute和property的區(qū)別是什么?

attribute是dom元素在文檔中作為html標(biāo)簽擁有的屬性;?

property就是dom元素在js中作為對象擁有的屬性。?

所以:?

對于html的標(biāo)準(zhǔn)屬性來說,attribute和property是同步的,是會(huì)自動(dòng)更新的,?

但是對于自定義的屬性來說,他們是不同步的,

4.src和href的區(qū)別

src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引用資源之間確立聯(lián)系。?

src是source的縮寫,指向外部資源的位置,指向的內(nèi)容將會(huì)嵌入到文檔中當(dāng)前標(biāo)簽所在位置;在請求src資源時(shí)會(huì)將其指向的資源下載并應(yīng)用到文檔內(nèi),當(dāng)瀏覽器解析到該元素時(shí),會(huì)暫停其他資源的下載和處理,直到將該資源加載、編譯、執(zhí)行完畢,圖片和框架等元素也如此,類似于將所指向資源嵌入當(dāng)前標(biāo)簽內(nèi)。這也是為什么將js腳本放在底部而不是頭部。?

Src source,指向外部資源的位置,如果我們添加瀏覽器會(huì)暫停其他資源的下載和處理,直到該資源加載,編譯,執(zhí)行完畢(圖片和框架也是如此),這也就是為什么js腳本要放在底部。?

src用于替換當(dāng)前元素,href用于在當(dāng)前文檔和引入資源之間建立聯(lián)系。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,489評論 0 21
  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,506評論 0 13
  • JavaScript,通??s寫為 JS,是一種解釋執(zhí)行的編程語言。它是現(xiàn)在最流行的腳本語言之一。 JavaScri...
    神齊閱讀 5,451評論 1 32
  • 男人扔下一句有事call我,奔麻將而去,另一人因他的離開而離開。說好今天有事三人行,如今剩下孤單的我佇立路中。委屈...
    靜看花落_7437閱讀 317評論 0 0
  • 明天走了,我應(yīng)該先改變自己! 還有五天,你能干什么?給我看看
    Whser閱讀 112評論 0 0

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