面經(jīng)之js

1.eval是做什么的?為什么盡量避免使用eval?

  1. Javascript全局對象,eval()函數(shù)可以計算機(jī)某個字符串,并計算其中的JS代碼。
    • eval只在被直接調(diào)用且調(diào)用函數(shù)就是eval本身時才會在當(dāng)前作用域執(zhí)行,否則會在全局作用域中執(zhí)行。
    • eval()可以干擾作用域鏈,eval()可以訪問和修改它外部作用域中的變量。
    • eval也存在安全問題,因為它會執(zhí)行任意傳給它的代碼, 在代碼字符串未知或者是來自一個不信任的源時,絕對不要使用eval函數(shù)。當(dāng)處理Ajax請求得到的JSON相應(yīng)的時候。在這些情況下,最好使用JavaScript內(nèi)置方法來解析JSON相應(yīng),以確保安全和有效。若瀏覽器不支持JSON.parse(),你可以使用來自JSON.org的庫。
    • eval不容易調(diào)試。用chromeDev等調(diào)試工具無法打斷點(diǎn)調(diào)試。
    • 說到性能問題,在舊的瀏覽器中如果你使用了eval,性能會下降10倍。在現(xiàn)代瀏覽器中有兩種編譯模式:fast path和slow path。fast path是編譯那些穩(wěn)定和可預(yù)測(stable and predictable)的代碼。而明顯的,eval不可預(yù)測,所以將會使用slow path,所以會慢。(2次,一次解析js,一次執(zhí)行。)

2.null和undefined的區(qū)別?

  1. undefined類型值只有一個即undefined, 當(dāng)聲明的變量還未被初始化時,變量的默認(rèn)值為undefined。
  2. Null類型的值只有一個即null,null用來表示尚未存在的對象,常用來表示函數(shù)企圖返回一個不存在的對象。
    alert(typeof undefined); //output "undefined"  
    alert(typeof null); //output "object"

第一行代碼很容易理解,undefined的類型為Undefined;第二行代碼卻讓人疑惑,為什么null的類型又是Object了呢?其實這是JavaScript最初實現(xiàn)的一個錯誤,后來被ECMAScript沿用下來。在今天我們可以解釋為,null即是一個不存在的對象的占位符,但是在實際編碼時還是要注意這一特性。

    alert(null == undefined); //output "true"     

ECMAScript認(rèn)為undefined是從null派生出來的,所以把它們定義為相等的。但是,如果在一些情況下,我們一定要區(qū)分這兩個值,那應(yīng)該怎么辦呢?可以使用下面的兩種方法。

      alert(null === undefined); //output "false"  
      alert(typeof null == typeof undefined); //output "false" 

使用typeof方法在前面已經(jīng)講過,null與undefined的類型是不一樣的,所以輸出"false"。而===代表絕對等于,在這里null === undefined輸出false。


2 寫一個通用的事件偵聽器函數(shù)。

     // event(事件)工具集,來源:github.com/markyun
       markyun.Event = {
           // 頁面加載完成后
           readyEvent : function(fn) {
               if (fn==null) {
                   fn=document;
               }
               var oldonload = window.onload;
               if (typeof window.onload != 'function') {
                   window.onload = fn;
               } else {
                   window.onload = function() {
                       oldonload();
                       fn();
                   };
               }
           },
           // 視能力分別使用dom0||dom2||IE方式 來綁定事件
           // 參數(shù): 操作的元素,事件名稱 ,事件處理程序
           addEvent : function(element, type, handler) {
               if (element.addEventListener) {
                   //事件類型、需要執(zhí)行的函數(shù)、是否捕捉
                   element.addEventListener(type, handler, false);
               } else if (element.attachEvent) {
                   element.attachEvent('on' + type, function() {
                       handler.call(element);
                   });
               } else {
                   element['on' + type] = handler;
               }
           },
           // 移除事件
           removeEvent : function(element, type, handler) {
               if (element.removeEventListener) {
                   element.removeEventListener(type, handler, false);
               } else if (element.datachEvent) {
                   element.detachEvent('on' + type, handler);
               } else {
                   element['on' + type] = null;
               }
           },
           // 阻止事件 (主要是事件冒泡,因為IE不支持事件捕獲)
           stopPropagation : function(ev) {
               if (ev.stopPropagation) {
                   ev.stopPropagation();
               } else {
                   ev.cancelBubble = true;
               }
           },
           // 取消事件的默認(rèn)行為
           preventDefault : function(event) {
               if (event.preventDefault) {
                   event.preventDefault();
               } else {
                   event.returnValue = false;
               }
           },
           // 獲取事件目標(biāo)
           getTarget : function(event) {
               return event.target || event.srcElement;
           },
           // 獲取event對象的引用,取到事件的所有信息,確保隨時能使用event;
           getEvent : function(e) {
               var ev = e || window.event;
               if (!ev) {
                   var c = this.getEvent.caller;
                   while (c) {
                       ev = c.arguments[0];
                       if (ev && Event == ev.constructor) {
                           break;
                       }
                       c = c.caller;
                   }
               }
               return ev;
           }
       };

3.模塊化怎么做?

立即執(zhí)行函數(shù),不暴露私有成員

        var module1 = (function(){
            var _count = 0;
            var m1 = function(){
              //...
            };
            var m2 = function(){
              //...
            };
            return {
              m1 : m1,
              m2 : m2
            };
          })();

4."use strict";是什么意思 ? 使用它的好處和壞處分別是什么?

ECMAscript 5添加了第二種運(yùn)行模式:"嚴(yán)格模式"(strict mode)。顧名思義,這種模式使得Javascript在更嚴(yán)格的條件下運(yùn)行。

設(shè)立"嚴(yán)格模式"的目的,主要有以下幾個:

1. 消除Javascript語法的一些不合理、不嚴(yán)謹(jǐn)之處,減少一些怪異行為;

2. 消除代碼運(yùn)行的一些不安全之處,保證代碼運(yùn)行的安全;

3. 提高編譯器效率,增加運(yùn)行速度;

4. 為未來新版本的Javascript做好鋪墊。

注:經(jīng)過測試 IE6,7,8,9 均不支持嚴(yán)格模式。

缺點(diǎn):

現(xiàn)在網(wǎng)站的 JS 都會進(jìn)行壓縮,一些文件用了嚴(yán)格模式,而另一些沒有。這時這些本來是嚴(yán)格模式的文件,被 merge后,這個串就到了文件的中間,不僅沒有指示嚴(yán)格模式,反而在壓縮后浪費(fèi)了字節(jié)。

怎么寫

首先嚴(yán)格模式可以寫在整個腳本或模塊中,也可以寫在函數(shù)中.如果寫在全局環(huán)境,可以直接在文件的第一句加入"use strict"就可以了. 但是如果這么寫的話你就慘了.
假如你的文件引入其它腳本文件時.假如其它腳本沒有啟用嚴(yán)格模式你將面臨很多問題.所以建議把嚴(yán)格模式寫在函數(shù)中,寫在函數(shù)內(nèi)的第一句就可以了.

作用

去除with關(guān)鍵字,使用嚴(yán)格模式后,with關(guān)鍵字會報錯不支持

with(){
}

這樣的寫法了.

防止意外的全局變量,這樣不帶var的聲明變量也不可以了.

a = 2; 

函數(shù)中未定義或者為null的this不在指向全局變量.防止依賴函數(shù)中的默認(rèn)this行為代碼出錯.

//"use strict"
this.color = "red";
function sayColor() {
    console.log(this.color);
}
sayColor();\\undefined
sayColor.call(null);\\undefined

嚴(yán)格模式

"use strict"
this.color = "red";
function sayColor() {
    console.log(this.color);
}
sayColor();
sayColor.call(null);

console.log(this.color);//TypeError: Cannot read property 'color' of undefined

另一種情況

"use strict"
function Person(name) {
    this.name = name;
}

var me = Person("Nicholas");

this.name = name;
              ^
TypeError: Cannot set property 'name' of undefined

原型繼承

"use strict"
function Person(name) {
    this.name = name;
}

var me = new Person("Nicholas");

沒有報錯. 原來這樣. this = proto = prototype 這些屬性都是在new 一個新的對象. 就是在原型繼承的時候賦值的.

重命名變量會報錯,這個不多說了,都理解.

安全的eval()

``js
//"use strict";
var y = eval("var x=10;");
console.log(x); //10

```js
 "use strict";
    var y = eval("var x=10;");
    console.log(x);
    console.log(x);
                ^
ReferenceError: x is not defined

禁止對只讀屬性賦值

// "use strict";
    var person = {};
    Object.defineProperty(person, "name",{
        writable: false,
            value: "Nicholas"
    });
    person.name = "John";

以上正確

"use strict";
    var person = {};
    Object.defineProperty(person, "name",{
        writable: false,
            value: "Nicholas"
    });

    person.name = "John";

報錯:

c:\Users\Feng Huang\WebstormProjects\MemberManagement\test4.js:13
    person.name = "John";
                ^
TypeError: Cannot assign to read only property 'name' of #<Object>

提示只讀屬性不能賦值.

new操作符具體干了什么呢?

1、創(chuàng)建一個空對象,并且 this 變量引用該對象,同時還繼承了該函數(shù)的原型。
2、屬性和方法被加入到 this 引用的對象中。
3、新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this 。

   var obj  = {};
   obj.__proto__ = Base.prototype;
   Base.call(obj);

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

hasOwnProperty()

["1", "2", "3"].map(parseInt) 答案是多少?

[1, NaN, NaN] 因為 parseInt 需要兩個參數(shù) (val, radix),其中 radix 表示解析時用的基數(shù)。map 傳了 3 個 (element, index, array),對應(yīng)的 radix 不合法導(dǎo)致解析失敗。

談?wù)凾his對象的理解。

this是js的一個關(guān)鍵字,隨著函數(shù)使用場合不同,this的值會發(fā)生變化。 但是有一個總原則,那就是this指的是調(diào)用函數(shù)的那個對象。 this一般情況下:是全局對象Global。 作為方法調(diào)用,那么this就是指這個對象.

js延遲加載的方式有哪些?

defer和async、動態(tài)創(chuàng)建DOM方式(用得最多)、按需異步載入js.

defer

定義和用法

defer 屬性規(guī)定是否對腳本執(zhí)行進(jìn)行延遲,直到頁面加載為止。
有的 javascript 腳本 document.write 方法來創(chuàng)建當(dāng)前的文檔內(nèi)容,其他腳本就不一定是了。
如果您的腳本不會改變文檔的內(nèi)容,可將 defer 屬性加入到 <script> 標(biāo)簽中,以便加快處理文檔的速度。因為瀏覽器知道它將能夠安全地讀取文檔的剩余部分而不用執(zhí)行腳本,它將推遲對腳本的解釋,直到文檔已經(jīng)顯示給用戶為止。

瀏覽器支持

只有 Internet Explorer (9以前)支持 defer 屬性。

async

定義和用法

async 屬性規(guī)定一旦腳本可用,則會異步執(zhí)行。
注釋:async 屬性僅適用于外部腳本(只有在使用 src 屬性時)。
注釋:有多種執(zhí)行外部腳本的方法:

  • 如果 async="async":腳本相對于頁面的其余部分異步地執(zhí)行(當(dāng)頁面繼續(xù)進(jìn)行解析時,腳本將被執(zhí)行)
  • 如果不使用 async 且 defer="defer":腳本將在頁面完成解析時執(zhí)行
  • 如果既不使用 async 也不使用 defer:在瀏覽器繼續(xù)解析頁面之前,立即讀取并執(zhí)行腳本

語法

<script async="async">

HTML 4.01 與 HTML 5 之間的差異

async 屬性是 HTML5 中的新屬性

async和defer 的區(qū)別

defer 屬性標(biāo)注的腳本是延遲腳本,使得瀏覽器延遲腳本的執(zhí)行,也就是說,腳本會被異步下載但是不會被執(zhí)行,直到文檔的載入和解析完成,并可以操作,腳本才會被執(zhí)行。
async 屬性標(biāo)注的腳本是異步腳本,即異步下載腳本時,不會阻塞文檔解析,但是一旦下載完成后,立即執(zhí)行,阻塞文檔解析。
延遲腳本會按他們在文檔里的出現(xiàn)順序執(zhí)行
異步腳本在它們載入后執(zhí)行,但是不能保證執(zhí)行順序。
使用async的意義就在于使得下載腳本時,不會阻塞文檔的解析。因為async的腳本執(zhí)行順序是沒有保證的,因此要確認(rèn)腳本間沒有依賴關(guān)系。
現(xiàn)在呢基本上都是在文檔的最后寫腳本,那么這和 defer 的區(qū)別在哪里呢?
第一點(diǎn)當(dāng)然是異步下載腳本了,第二點(diǎn)就是 使用async或defer任何一個都意味著在腳本里不能出現(xiàn) document.write。

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

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

  • 第一章: JS簡介 從當(dāng)初簡單的語言,變成了現(xiàn)在能夠處理復(fù)雜計算和交互,擁有閉包、匿名函數(shù), 甚至元編程等...
    LaBaby_閱讀 1,758評論 0 6
  • 有人說過,很多彎路到最后都成了直路,所有的坑到最后也都成了坦途;所謂的直路和坦途并不是擺在眼前的,都是不斷的的...
    老衲法號一眉道人閱讀 1,457評論 0 4
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進(jìn)階之旅閱讀 115,545評論 24 450
  • 天還沒亮,一個人開著車馳騁在熟悉的路上,仗著大清早路上沒幾輛車,油門不自覺踩的比平常要深一些。鄉(xiāng)下公路沒有路燈,司...
    李詩民閱讀 1,354評論 7 4
  • 最近總有人提起思維導(dǎo)圖 讓我想起我最早接觸思維導(dǎo)圖的夏令營 可惜沒什么照片可作紀(jì)念 很想要當(dāng)時畫的第一張思維導(dǎo)圖(...
    UKA的嗯閱讀 339評論 0 0

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