前端面試(三)JavaScript

lkycan發表於2017-12-14

###介紹js的基本資料型別。

 Undefined、Null、Boolean、Number、String
複製程式碼

###介紹js有哪些內建物件?

Object 是 JavaScript 中所有物件的父物件
資料封裝類物件:Object、Array、Boolean、Number 和 String
其他物件:Function、Arguments、Math、Date、RegExp、Error
複製程式碼

###說幾條寫JavaScript的基本規範?

1.不要在同一行宣告多個變數。
2.請使用 ===/!==來比較true/false或者數值
3.使用物件字面量替代new Array這種形式
4.不要使用全域性函式。
5.Switch語句必須帶有default分支
6.函式不應該有時候有返回值,有時候沒有返回值。
7.For迴圈必須使用大括號
8.If語句必須使用大括號
9.for-in迴圈中的變數 應該使用var關鍵字明確限定作用域,從而避免作用域汙染。
複製程式碼

###JavaScript原型,原型鏈 ? 有什麼特點? 每個物件都會在其內部初始化一個屬性,就是prototype(原型),當我們訪問一個物件的屬性時,如果這個物件內部不存在這個屬性,那麼他就會去prototype裡找這個屬性,這個prototype又會有自己的prototype,於是就這樣一直找下去,也就是我們平時所說的原型鏈的概念。

關係:instance.constructor.prototype = instance.proto 特點: JavaScript物件是通過引用來傳遞的,我們建立的每個新物件實體中並沒有一份屬於自己的原型副本。 當我們修改原型時,與之相關的物件也會繼承這一改變。 當我們需要一個屬性的時,Javascript引擎會先看當前物件中是否有這個屬性, 如果沒有的話, 就會查詢他的Prototype物件是否有這個屬性,如此遞推下去,一直檢索到 Object 內建物件。

function Func(){} Func.prototype.name = "Sean"; 
Func.prototype.getInfo = function() { return this.name; } 
var person = new Func();//現在可以參考var person = Object.create(oldObject); 
console.log(person.getInfo());//它擁有了Func的屬性和方法 
//"Sean"
 console.log(Func.prototype);
// Func { name="Sean", getInfo=function()}
複製程式碼

###JavaScript有幾種型別的值?,你能畫一下他們的記憶體圖嗎? 棧:原始資料型別(Undefined,Null,Boolean,Number、String)

堆:引用資料型別(物件、陣列和函式)

兩種型別的區別是:儲存位置不同; 原始資料型別直接儲存在棧(stack)中的簡單資料段,佔據空間小、大小固定,屬於被頻繁使用資料,所以放入棧中儲存; 引用資料型別儲存在堆(heap)中的物件,佔據空間大、大小不固定,如果儲存在棧中,將會影響程式執行的效能; 引用資料型別在棧中儲存了指標,該指標指向堆中該實體的起始地址。當直譯器尋找引用值時,會首先檢索其在棧中的地址,取得地址後從堆中獲得實體

Stated Clearly Image

###Javascript如何實現繼承? 1、構造繼承 2、原型繼承 3、例項繼承 4、拷貝繼承原型prototype機制或apply和call方法去實現較簡單,建議使用建構函式與原型混合方式。

 function Parent(){ 
      this.name = 'wang'; 
} 
function Child(){
         this.age = 28;
 }

 Child.prototype = new Parent();//繼承了Parent,通過原型 

var demo = new Child(); alert(demo.age); alert(demo.name);//得到被繼承的屬性 
}
複製程式碼

###JavaScript繼承的幾種實現方式?

###javascript建立物件的幾種方式? javascript建立物件簡單的說,無非就是使用內建物件或各種自定義物件,當然還可以用JSON;但寫法有很多種,也能混合使用。

1、物件字面量的方式
         person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};

2、用function來模擬無參的建構函式

     function Person(){} 
    var person=new Person();//定義一個function,如果使用new"例項化",該function可以看作是一個Class 
    person.name="Mark"; person.age="25"; 
    person.work=function(){
       alert(person.name+" hello..."); 
    }
    person.work();

3、用function來模擬參建構函式來實現(用this關鍵字定義構造的上下文屬性)

function Pet(name,age,hobby){    
       this.name=name;//this作用域:當前物件  
       this.age=age;    
       this.hobby=hobby;    
       this.eat=function(){        
       alert("我叫"+this.name+",我喜歡"+this.hobby+",是個程式設計師");    
}}
    var maidou =new Pet("麥兜",25,"coding");//例項化、建立物件
    maidou.eat();//呼叫eat方法

4、用工廠方式來建立(內建物件)
  
     var wcDog =new Object(); 
      wcDog.name="旺財"; 
      wcDog.age=3; 
      wcDog.work=function(){
                 alert("我是"+wcDog.name+",汪汪汪......"); 
       } 
      wcDog.work();

5、用原型方式來建立

 function Dog(){ } 
      Dog.prototype.name="旺財"; 
      Dog.prototype.eat=function(){ 
      alert(this.name+"是個吃貨"); 
}
     var wangcai =new Dog(); 
    wangcai.eat();


6、用混合方式來建立

 function Car(name,price){
     this.name=name;
      this.price=price;
 } 
  Car.prototype.sell=function(){ 
    alert("我是"+this.name+",我現在賣"+this.price+"萬元"); 
}
 var camry =new Car("凱美瑞",27); 
  camry.sell();
複製程式碼

###Javascript作用鏈域? 全域性函式無法檢視區域性函式的內部細節,但區域性函式可以檢視其上層的函式細節,直至全域性細節。當需要從區域性函式查詢某一屬性或方法時,如果當前作用域沒有找到,就會上溯到上層作用域查詢,直至全域性函式,這種組織形式就是作用域鏈。

###談談This物件的理解。

  • this總是指向函式的直接呼叫者(而非間接呼叫者);
  • 如果有new關鍵字,this指向new出來的那個物件;
  • 在事件中,this指向觸發這個事件的物件,特殊的是,IE中的attachEvent中的this總是指向全域性物件Window;

###eval是做什麼的? 它的功能是把對應的字串解析成JS程式碼並執行;應該避免使用eval,不安全,非常耗效能(2次,一次解析成js語句,一次執行)。由JSON字串轉換為JSON物件的時候可以用eval,var obj =eval('('+ str +')');

  • 什麼是window物件? 什麼是document物件? [BOM]就是瀏覽器視窗物件模型,頂級物件就是window

window,document都是一個例項物件,他們都屬於Object,你不可以在new他,必須直接呼叫他的方法和屬性

Window物件共有七個屬性:

defauleStatus:指定視窗狀態列中的資訊。

status:指定當前視窗狀態列中的資訊。

frames:是一個陣列,其中內容是視窗中所有的框架。

parent:指當前視窗的父視窗。

self:指當前視窗。

top:代表當前所有視窗的最頂層視窗。

window:代表當前視窗。

Window物件有五個方法:

alert:顯示帶有一個“確定”按鈕的對話方塊。

confirm:顯示帶有“確定”與“取消”兩個按鈕的對話方塊。

prompt:顯示帶有輸入區的對話方塊。

open:開啟一個新視窗。

close:關閉使用者開啟的視窗。

###null,undefined 的區別?

null 表示一個物件被定義了,值為“空值”;
undefined 表示不存在這個值。
typeof undefined //"undefined" 
undefined :是一個表示"無"的原始值或者說表示"缺少值",就是此處應該有一個值,但是還沒有定義。
當嘗試讀取時會返回 undefined;
例如變數被宣告瞭,但沒有賦值時,就等於undefined

typeof null //"object" null : 是一個物件(空物件, 沒有任何屬性和方法); 
例如作為函式的引數,表示該函式的引數不是物件;
注意: 在驗證null時,一定要使用 === ,因為 == 無法分別 null 和 undefined

再來一個例子:
null Q:有張三這個人麼?
   A:有! 
   Q:張三有房子麼?
   A:沒有! 
undefined 
    Q:有張三這個人麼? 
      A:沒有!
複製程式碼

參考閱讀:undefined與null的區別 ###寫一個通用的事件偵聽器函式



    // 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方式 來繫結事件
    // 引數: 操作的元素,事件名稱 ,事件處理程式
    addEvent : function(element, type, handler) {
        if (element.addEventListener) {
            //事件型別、需要執行的函式、是否捕捉
            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;
        }
    },
    // 取消事件的預設行為
    preventDefault : function(event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    // 獲取事件目標
    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;
    }
};
複製程式碼

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

[1, NaN, NaN] 因為 parseInt 需要兩個引數 (val, radix),
其中 radix 表示解析時用的基數。
map 傳了 3 個 (element, index, array),對應的 radix 不合法導致解析失敗。
複製程式碼

###事件是?IE與火狐的事件機制有什麼區別? 如何阻止冒泡?

1. 我們在網頁中的某個操作(有的操作對應多個事件)。例如:當我們點選一個按鈕就會產生一個事件。是可以被 JavaScript 偵測到的行為。
2. 事件處理機制:IE是事件冒泡、Firefox同時支援兩種事件模型,也就是:捕獲型事件和冒泡型事件;
3. ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)
複製程式碼

###什麼是閉包(closure),為什麼要用它?

閉包是指有權訪問另一個函式作用域中變數的函式,建立閉包的最常見的方式就是在一個函式內建立另一個函式,通過另一個函式訪問這個函式的區域性變數,利用閉包可以突破作用鏈域,將函式內部的變數和方法傳遞到外部。

閉包的特性:

1.函式內再巢狀函式
2.內部函式可以引用外層的引數和變數
3.引數和變數不會被垃圾回收機制回收

//li節點的onclick事件都能正確的彈出當前被點選的li索引
<ul>
<li> index = 0</li>
<li> index = 1</li>
<li> index = 2</li>
<li> index = 3</li>
    </ul>
    <script type="text/javascript">
var nodes = document.getElementsByTagName("li");
for(i = 0;i<nodes.length;i+= 1){
    nodes[i].onclick = function(){
        console.log(i+1);//不用閉包的話,值每次都是4
    }(i);
}
</script>

執行say667()後,say667()閉包內部變數會存在,而閉包內部函式的內部變數不會存在
使得Javascript的垃圾回收機制GC不會收回say667()所佔用的資源
因為say667()的內部函式的執行需要依賴say667()中的變數
這是對閉包作用的非常直白的描述

function say667() {
    // Local variable that ends up within closure
    var num = 666;
    var sayAlert = function() {
        alert(num);
    }
    num++;
    return sayAlert;
}

var sayAlert = say667();
sayAlert()//執行結果應該彈出的667
複製程式碼

###javascript 程式碼中的"use strict";是什麼意思 ? 使用它區別是什麼?

use strict是一種ECMAscript 5 新增的(嚴格)執行模式,這種模式使得 Javascript 在更嚴格的條件下執行,

    使JS編碼更加規範化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為。
預設支援的糟糕特性都會被禁用,比如不能用with,也不能在意外的情況下給全域性變數賦值;
全域性變數的顯示宣告,函式必須宣告在頂層,不允許在非函式程式碼塊內宣告函式,arguments.callee也不允許使用;
消除程式碼執行的一些不安全之處,保證程式碼執行的安全,限制函式中的arguments修改,嚴格模式下的eval函式的行為和非嚴格模式的也不相同;

提高編譯器效率,增加執行速度;
為未來新版本的Javascript標準化做鋪墊。
複製程式碼

###如何判斷一個物件是否屬於某個類?

 使用instanceof (待完善) 
    if(a instanceof Person){ 
        alert('yes');
 }
複製程式碼

###new操作符具體幹了什麼呢?

 1、建立一個空物件,並且 this 變數引用該物件,同時還繼承了該函式的原型。 
2、屬性和方法被加入到 this 引用的物件中。 
3、新建立的物件由 this 所引用,並且最後隱式的返回 this 。
     var obj = {};obj.__proto__ = Base.prototype;Base.call(obj);
複製程式碼

###用原生JavaScript的實現過什麼功能嗎?

......
複製程式碼

###Javascript中,有一個函式,執行時物件查詢時,永遠不會去查詢原型,這個函式是?

hasOwnProperty

javaScript中hasOwnProperty函式方法是返回一個布林值,指出一個物件是否具有指定名稱的屬性。
此方法無法檢查該物件的原型鏈中是否具有該屬性;該屬性必須是物件本身的一個成員。
使用方法:
object.hasOwnProperty(proName)
其中引數object是必選項。一個物件的例項。
proName是必選項。一個屬性名稱的字串值。

如果 object 具有指定名稱的屬性,那麼JavaScript 中 hasOwnProperty函式方法返回 true,
反之則返回 false複製程式碼

###JSON 的瞭解?

JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。
它是基於JavaScript的一個子集。資料格式簡單, 易於讀寫, 佔用頻寬小
如:{"age":"12", "name":"back"}

JSON字串轉換為JSON物件:
var obj =eval('('+ str +')');
var obj = str.parseJSON();
var obj = JSON.parse(str);

JSON物件轉換為JSON字串:
var last=obj.toJSONString();
var last=JSON.stringify(obj);
複製程式碼

###[].forEach.call($$(""),function(a){a.style.outline="1px solid #"+(~~(Math.random()(1<<24))).tostring(16)})< code=""> 能解釋一下這段程式碼的意思嗎?</24))).tostring(16)})<>

###js延遲載入的方式有哪些?

defer和async、動態建立DOM方式(用得最多)、按需非同步載入js  
複製程式碼

###Ajax 是什麼? 如何建立一個Ajax?

ajax的全稱:Asynchronous Javascript And XML。
非同步傳輸+js+xml。
所謂非同步,在這裡簡單地解釋就是:向伺服器傳送請求的時候,我們不必等待結果,
而是可以同時做其他的事情,等到有了結果它自己會根據設定進行後續操作,
與此同時,頁面是不會發生整頁重新整理的,提高了使用者體驗。

(1)建立XMLHttpRequest物件,也就是建立一個非同步呼叫物件
(2)建立一個新的HTTP請求,並指定該HTTP請求的方法、URL及驗證資訊
(3)設定響應HTTP請求狀態變化的函式
(4)傳送HTTP請求
(5)獲取非同步呼叫返回的資料
(6)使用JavaScript和DOM實現區域性重新整理
複製程式碼

###同步和非同步的區別?

同步的概念應該是來自於OS中關於同步的概念:
不同程式為協同完成某項工作而在先後次序上調整(通過阻塞,喚醒等方式).
同步強調的是順序性.誰先誰後.非同步則不存在這種順序性.

 同步:瀏覽器訪問伺服器請求,使用者看得到頁面重新整理,
      重新發請求,等請求完,頁面重新整理,新內容出現,使用者看到新內容,進行下一步操作。

非同步:瀏覽器訪問伺服器請求,使用者正常操作,瀏覽器後端進行請求。
      等請求完,頁面不重新整理,新內容也會出現,使用者看到新內容。

(待完善)
複製程式碼

###如何解決跨域問題?

jsonp、 iframe、window.name、window.postMessage、伺服器上設定代理頁面
複製程式碼

###頁面編碼和被請求的資源編碼如果不一致如何處理? ###模組化開發怎麼做? 立即執行函式,不暴露私有成員

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

(待續)
複製程式碼

###AMD(Modules/Asynchronous-Definition)、CMD(Common Module Definition)規範區別?
AMD 規範在這裡:github.com/amdjs/amdjs… CMD 規範在這裡:github.com/seajs/seajs…

Asynchronous Module Definition,非同步模組定義,所有的模組將被非同步載入,模組載入不影響後面語句執行。所有依賴某些模組的語句均放置在回撥函式中。

區別:

1. 對於依賴的模組,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
2. CMD 推崇依賴就近,AMD 推崇依賴前置。看程式碼:

// CMD
define(function(require, exports, module) {
    var a = require('./a')
    a.doSomething()
    // 此處略去 100 行
    var b = require('./b') // 依賴可以就近書寫
    b.doSomething()
    // ...
})

// AMD 預設推薦
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
    a.doSomething()
    // 此處略去 100 行
    b.doSomething()
    // ...
})
複製程式碼
  • requireJS的核心原理是什麼?(如何動態載入的?如何避免多次載入的?如何快取的?)

  • 談一談你對ECMAScript6的瞭解?

  • ECMAScript6 怎麼寫class麼,為什麼會出現class這種東西?

###非同步載入JS的方式有哪些?

 (1) defer,只支援IE 
(2) async: 
(3) 建立script,插入到DOM中,載入完畢後callBack
複製程式碼

###documen.write和 innerHTML的區別

document.write    只能重繪整個頁面
innerHTML    可以重繪頁面的一部分
複製程式碼

###DOM操作——怎樣新增、移除、移動、複製、建立和查詢節點?

(1)建立新節點
createDocumentFragment()    //建立一個DOM片段
createElement()   //建立一個具體的元素
createTextNode()   //建立一個文字節點
(2)新增、移除、替換、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子節點前插入一個新的子節點
(3)查詢
getElementsByTagName()    //通過標籤名稱
getElementsByName()    //通過元素的Name屬性的值(IE容錯能力較強,會得到一個陣列,其中包括id等於name值的)
getElementById()    //通過元素Id,唯一性
複製程式碼

###.call() 和 .apply() 的區別?

例子中用 add 來替換 sub,add.call(sub,3,1) == add(3,1) ,所以執行結果為:alert(4);

注意:js 中的函式其實是物件,函式名是對 Function 物件的引用。

function add(a,b)
{
    alert(a+b);
}

function sub(a,b)
{
    alert(a-b);
}

add.call(sub,3,1);
複製程式碼
  • 陣列和物件有哪些原生方法,列舉一下?

  • JS 怎麼實現一個類。怎麼例項化這個類

  • JavaScript中的作用域與變數宣告提升?

  • 如何編寫高效能的Javascript?

  • 那些操作會造成記憶體洩漏?

  • JQuery的原始碼看過嗎?能不能簡單概況一下它的實現原理?

  • jQuery.fn的init方法返回的this指的是什麼物件?為什麼要返回this?

  • jquery中如何將陣列轉化為json字串,然後再轉化回來?

  • jQuery 的屬性拷貝(extend)的實現原理是什麼,如何實現深拷貝?

  • jquery.extend 與 jquery.fn.extend的區別?

  • jQuery 的佇列是如何實現的?佇列可以用在哪些地方?

  • 談一下Jquery中的bind(),live(),delegate(),on()的區別?

  • JQuery一個物件可以同時繫結多個事件,這是如何實現的?

  • 是否知道自定義事件。jQuery裡的fire函式是什麼意思,什麼時候用?

  • jQuery 是通過哪個方法和 Sizzle 選擇器結合的?(jQuery.fn.find()進入Sizzle)

  • 針對 jQuery效能的優化方法?

###Jquery與jQuery UI 有啥區別?

**jQuery是一個js庫,主要提供的功能是選擇器,屬性修改和事件繫結等等。

**jQuery UI則是在jQuery的基礎上,利用jQuery的擴充套件性,設計的外掛。
提供了一些常用的介面元素,諸如對話方塊、拖動行為、改變大小行為等等
複製程式碼

###JQuery的原始碼看過嗎?能不能簡單說一下它的實現原理?

...
複製程式碼

###jquery 中如何將陣列轉化為json字串,然後再轉化回來? jQuery中沒有提供這個功能,所以你需要先編寫兩個jQuery的擴充套件:

$.fn.stringifyArray = function(array) {
    return JSON.stringify(array)
}

$.fn.parseArray = function(array) {
    return JSON.parse(array)
}

然後呼叫:
$("").stringifyArray(array)
複製程式碼

###jQuery和Zepto的區別?各自的使用場景?

...
複製程式碼

###針對 jQuery 的優化方法?

*基於Class的選擇性的效能相對於Id選擇器開銷很大,因為需遍歷所有DOM元素。

*頻繁操作的DOM,先快取起來再操作。用Jquery的鏈式呼叫更好。
比如:var str=$("a").attr("href");

*for (var i = size; i < arr.length; i++) {}
for 迴圈每一次迴圈都查詢了陣列 (arr) 的.length 屬性,在開始迴圈的時候設定一個變數來儲存這個數字,可以讓迴圈跑得更快:
for (var i = size, length = arr.length; i < length; i++) {}
複製程式碼

###Zepto的點透問題如何解決?

...
複製程式碼

###jQueryUI如何自定義元件?

...
複製程式碼

###需求:實現一個頁面操作不會整頁重新整理的網站,並且能在瀏覽器前進、後退時正確響應。給出你的技術實現方案?

...
複製程式碼

收集於網路 待續......

相關文章