成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

前端面試題(4)JavaScript

王晗 / 1182人閱讀

摘要:變量聲明提升在中,函數(shù)聲明與變量聲明經(jīng)常被引擎隱式地提升到當前作用域的頂部。對象的方法和屬性是在全局范圍內(nèi)有效的。未形成標準,實現(xiàn)混亂。

前端面試題JavaScript(一)

JavaScript的組成

JavaScript 由以下三部分組成:

ECMAScript(核心):JavaScript 語言基礎(chǔ)

DOM(文檔對象模型):規(guī)定了訪問HTML和XML的接口

BOM(瀏覽器對象模型):提供了瀏覽器窗口之間進行交互的對象和方法

JS的基本數(shù)據(jù)類型和引用數(shù)據(jù)類型

基本數(shù)據(jù)類型:undefined、null、boolean、number、string、symbol

引用數(shù)據(jù)類型:object、array、function

檢測瀏覽器版本版本有哪些方式?

根據(jù) navigator.userAgent // UA.toLowerCase().indexOf("chrome")

根據(jù) window 對象的成員 // "ActiveXObject" in window

介紹JS有哪些內(nèi)置對象?

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

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

ES6新增對象:Symbol、Map、Set、Promises、Proxy、Reflect

說幾條寫JavaScript的基本規(guī)范?

代碼縮進,建議使用“四個空格”縮進

代碼段使用花括號{}包裹

語句結(jié)束使用分號;

變量和函數(shù)在使用前進行聲明

以大寫字母開頭命名構(gòu)造函數(shù),全大寫命名常量

規(guī)范定義JSON對象,補全雙引號

用{}和[]聲明對象和數(shù)組

如何編寫高性能的JavaScript?

遵循嚴格模式:"use strict";

將js腳本放在頁面底部,加快渲染頁面

將js腳本將腳本成組打包,減少請求

使用非阻塞方式下載js腳本

盡量使用局部變量來保存全局變量

盡量減少使用閉包

使用 window 對象屬性方法時,省略 window

盡量減少對象成員嵌套

緩存 DOM 節(jié)點的訪問

通過避免使用 eval() 和 Function() 構(gòu)造器

給 setTimeout() 和 setInterval() 傳遞函數(shù)而不是字符串作為參數(shù)

盡量使用直接量創(chuàng)建對象和數(shù)組

最小化重繪(repaint)和回流(reflow)

描述瀏覽器的渲染過程,DOM樹和渲染樹的區(qū)別?

瀏覽器的渲染過程:

解析HTML構(gòu)建 DOM(DOM樹),并行請求 css/image/js

CSS 文件下載完成,開始構(gòu)建 CSSOM(CSS樹)

CSSOM 構(gòu)建結(jié)束后,和 DOM 一起生成 Render Tree(渲染樹)

布局(Layout):計算出每個節(jié)點在屏幕中的位置

顯示(Painting):通過顯卡把頁面畫到屏幕上

DOM樹 和 渲染樹 的區(qū)別:

DOM樹與HTML標簽一一對應(yīng),包括head和隱藏元素

渲染樹不包括head和隱藏元素,大段文本的每一個行都是獨立節(jié)點,每一個節(jié)點都有對應(yīng)的css屬性

重繪和回流(重排)的區(qū)別和關(guān)系?

重繪:當渲染樹中的元素外觀(如:顏色)發(fā)生改變,不影響布局時,產(chǎn)生重繪

回流:當渲染樹中的元素的布局(如:尺寸、位置、隱藏/狀態(tài)狀態(tài))發(fā)生改變時,產(chǎn)生重繪回流

注意:JS獲取Layout屬性值(如:offsetLeft、scrollTop、getComputedStyle等)也會引起回流。因為瀏覽器需要通過回流計算最新值

回流必將引起重繪,而重繪不一定會引起回流

如何最小化重繪(repaint)和回流(reflow)?

需要要對元素進行復(fù)雜的操作時,可以先隱藏(display:"none"),操作完成后再顯示

需要創(chuàng)建多個DOM節(jié)點時,使用DocumentFragment創(chuàng)建完后一次性的加入document

緩存Layout屬性值,如:var left = elem.offsetLeft; 這樣,多次使用 left 只產(chǎn)生一次回流

盡量避免用table布局(table元素一旦觸發(fā)回流就會導(dǎo)致table里所有的其它元素回流)

避免使用css表達式(expression),因為每次調(diào)用都會重新計算值(包括加載頁面)

盡量使用 css 屬性簡寫,如:用 border 代替 border-width, border-style, border-color

批量修改元素樣式:elem.className 和 elem.style.cssText 代替 elem.style.xxx

script 的位置是否會影響首屏顯示時間?

在解析 HTML 生成 DOM 過程中,js 文件的下載是并行的,不需要 DOM 處理到 script 節(jié)點。因此,script的位置不影響首屏顯示的開始時間。

瀏覽器解析 HTML 是自上而下的線性過程,script作為 HTML 的一部分同樣遵循這個原則

因此,script 會延遲 DomContentLoad,只顯示其上部分首屏內(nèi)容,從而影響首屏顯示的完成時間

解釋JavaScript中的作用域與變量聲明提升?

JavaScript作用域:

在Java、C等語言中,作用域為for語句、if語句或{}內(nèi)的一塊區(qū)域,稱為作用域;

而在 JavaScript 中,作用域為function(){}內(nèi)的區(qū)域,稱為函數(shù)作用域。

JavaScript變量聲明提升:

在JavaScript中,函數(shù)聲明與變量聲明經(jīng)常被JavaScript引擎隱式地提升到當前作用域的頂部。

聲明語句中的賦值部分并不會被提升,只有名稱被提升

函數(shù)聲明的優(yōu)先級高于變量,如果變量名跟函數(shù)名相同且未賦值,則函數(shù)聲明會覆蓋變量聲明

如果函數(shù)有多個同名參數(shù),那么最后一個參數(shù)(即使沒有定義)會覆蓋前面的同名參數(shù)

介紹JavaScript的原型,原型鏈?有什么特點?

原型:

JavaScript的所有對象中都包含了一個 [__proto__] 內(nèi)部屬性,這個屬性所對應(yīng)的就是該對象的原型

JavaScript的函數(shù)對象,除了原型 [__proto__] 之外,還預(yù)置了 prototype 屬性

當函數(shù)對象作為構(gòu)造函數(shù)創(chuàng)建實例時,該 prototype 屬性值將被作為實例對象的原型 [__proto__]。

原型鏈:

當一個對象調(diào)用的屬性/方法自身不存在時,就會去自己 [__proto__] 關(guān)聯(lián)的前輩 prototype 對象上去找

如果沒找到,就會去該 prototype 原型 [__proto__] 關(guān)聯(lián)的前輩 prototype 去找。依次類推,直到找到屬性/方法或 undefined 為止。從而形成了所謂的“原型鏈”

原型特點:

JavaScript對象是通過引用來傳遞的,當修改原型時,與之相關(guān)的對象也會繼承這一改變

JavaScript有幾種類型的值

原始數(shù)據(jù)類型(Undefined,Null,Boolean,Number、String)-- 棧

引用數(shù)據(jù)類型(對象、數(shù)組和函數(shù))-- 堆

兩種類型的區(qū)別是:存儲位置不同:

原始數(shù)據(jù)類型是直接存儲在棧(stack)中的簡單數(shù)據(jù)段,占據(jù)空間小、大小固定,屬于被頻繁使用數(shù)據(jù);

引用數(shù)據(jù)類型存儲在堆(heap)中的對象,占據(jù)空間大、大小不固定,如果存儲在棧中,將會影響程序運行的性能;

引用數(shù)據(jù)類型在棧中存儲了指針,該指針指向堆中該實體的起始地址。

當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址后從堆中獲得實體。

JavaScript如何實現(xiàn)一個類,怎么實例化這個類?

構(gòu)造函數(shù)法(this + prototype) -- 用 new 關(guān)鍵字 生成實例對象

缺點:用到了 this 和 prototype,編寫復(fù)雜,可讀性差

  function Mobile(name, price){
     this.name = name;
     this.price = price;
   }
   Mobile.prototype.sell = function(){
      alert(this.name + ",售價 $" + this.price);
   }
   var iPhone7 = new Mobile("iPhone7", 1000);
   iPhone7.sell();

Object.create 法 -- 用 Object.create() 生成實例對象

缺點:不能實現(xiàn)私有屬性和私有方法,實例對象之間也不能共享數(shù)據(jù)

 var Person = {
     firstname: "Mark",
     lastname: "Yun",
     age: 25,
     introduce: function(){
         alert("I am " + Person.firstname + " " + Person.lastname);
     }
 };

 var person = Object.create(Person);
 person.introduce();

 // Object.create 要求 IE9+,低版本瀏覽器可以自行部署:
 if (!Object.create) {
    Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
  };
 }

極簡主義法(消除 this 和 prototype) -- 調(diào)用 createNew() 得到實例對象

優(yōu)點:容易理解,結(jié)構(gòu)清晰優(yōu)雅,符合傳統(tǒng)的"面向?qū)ο缶幊?的構(gòu)造

 var Cat = {
   age: 3, // 共享數(shù)據(jù) -- 定義在類對象內(nèi),createNew() 外
   createNew: function () {
     var cat = {};
     // var cat = Animal.createNew(); // 繼承 Animal 類
     cat.name = "小咪";
     var sound = "喵喵喵"; // 私有屬性--定義在 createNew() 內(nèi),輸出對象外
     cat.makeSound = function () {
       alert(sound);  // 暴露私有屬性
     };
     cat.changeAge = function(num){
       Cat.age = num; // 修改共享數(shù)據(jù)
     };
     return cat; // 輸出對象
   }
 };

 var cat = Cat.createNew();
 cat.makeSound();

ES6 語法糖 class -- 用 new 關(guān)鍵字 生成實例對象

     class Point {
       constructor(x, y) {
         this.x = x;
         this.y = y;
       }
       toString() {
         return "(" + this.x + ", " + this.y + ")";
       }
     }

  var point = new Point(2, 3);

Javascript如何實現(xiàn)繼承?

構(gòu)造函數(shù)綁定:使用 call 或 apply 方法,將父對象的構(gòu)造函數(shù)綁定在子對象上

function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}

實例繼承:將子對象的 prototype 指向父對象的一個實例

Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

拷貝繼承:如果把父對象的所有屬性和方法,拷貝進子對象

    function extend(Child, Parent) {
     var p = Parent.prototype;
     var c = Child.prototype;
     for (var i in p) {
        c[i] = p[i];
     }
     c.uber = p;
    }

原型繼承:將子對象的 prototype 指向父對象的 prototype

    function extend(Child, Parent) {
        var F = function(){};
       F.prototype = Parent.prototype;
       Child.prototype = new F();
       Child.prototype.constructor = Child;
       Child.uber = Parent.prototype;
    }

ES6 語法糖 extends:class ColorPoint extends Point {}

    class ColorPoint extends Point {
       constructor(x, y, color) {
          super(x, y); // 調(diào)用父類的constructor(x, y)
          this.color = color;
       }
       toString() {
          return this.color + " " + super.toString(); // 調(diào)用父類的toString()
       }
    }

談?wù)則his對象的理解

this 總是指向函數(shù)的直接調(diào)用者

如果有 new 關(guān)鍵字,this 指向 new 出來的實例對象

在事件中,this指向觸發(fā)這個事件的對象

IE下 attachEvent 中的this總是指向全局對象Window

eval是做什么的?

eval的功能是把對應(yīng)的字符串解析成JS代碼并運行

應(yīng)該避免使用eval,不安全,非常耗性能(先解析成js語句,再執(zhí)行)

由JSON字符串轉(zhuǎn)換為JSON對象的時候可以用 eval("("+ str +")");

什么是 Window 對象? 什么是 Document 對象?

Window 對象表示當前瀏覽器的窗口,是JavaScript的頂級對象。

我們創(chuàng)建的所有對象、函數(shù)、變量都是 Window 對象的成員。

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

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

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

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

介紹 DOM 的發(fā)展

DOM:文檔對象模型(Document Object Model),定義了訪問HTML和XML文檔的標準,與編程語言及平臺無關(guān)

DOM0:提供了查詢和操作Web文檔的內(nèi)容API。未形成標準,實現(xiàn)混亂。如:document.forms["login"]

DOM1:W3C提出標準化的DOM,簡化了對文檔中任意部分的訪問和操作。如:JavaScript中的Document對象

DOM2:原來DOM基礎(chǔ)上擴充了鼠標事件等細分模塊,增加了對CSS的支持。如:getComputedStyle(elem, pseudo)

DOM3:增加了XPath模塊和加載與保存(Load and Save)模塊。如:XPathEvaluator

介紹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級事件

事件的三個階段

捕獲、目標、冒泡

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

按照W3C標準的事件:首是進入捕獲階段,直到達到目標元素,再進入冒泡階段

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

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

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

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

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

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

最終順序:父元素捕獲->目標元素事件1->目標元素事件2->子元素捕獲->子元素冒泡->父元素冒泡

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

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

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

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

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

事件的代理/委托

事件委托是指將事件綁定目標元素的到父元素上,利用冒泡機制觸發(fā)該事件

優(yōu)點:

可以減少事件注冊,節(jié)省大量內(nèi)存占用

可以將事件應(yīng)用于動態(tài)添加的子元素上

缺點:
使用不當會造成事件在不應(yīng)該觸發(fā)時觸發(fā)

示例:

ulEl.addEventListener("click", function(e){
    var target = event.target || event.srcElement;
    if(!!target && target.nodeName.toUpperCase() === "LI"){
        console.log(target.innerHTML);
    }
}, false);

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

IE只事件冒泡,不支持事件捕獲;火狐同時支持件冒泡和事件捕獲

IE的事件處理和W3C的事件處理有哪些區(qū)別?

綁定事件

W3C: targetEl.addEventListener("click", handler, false);

IE: targetEl.attachEvent("onclick", handler);

刪除事件

W3C: targetEl.removeEventListener("click", handler, false);

IE: targetEl.detachEvent(event, handler);

事件對象

W3C: var e = arguments.callee.caller.arguments[0]

IE: window.event

事件目標

W3C: e.target

IE: window.event.srcElement

阻止事件默認行為

W3C: e.preventDefault()

IE: window.event.returnValue = false

阻止事件傳播

W3C: e.stopPropagation()

IE: window.event.cancelBubble = true

W3C事件的 target 與 currentTarget 的區(qū)別?

target 只會出現(xiàn)在事件流的目標階段

currentTarget 可能出現(xiàn)在事件流的任何階段

當事件流處在目標階段時,二者的指向相同

當事件流處于捕獲或冒泡階段時:currentTarget 指向當前事件活動的對象(一般為父級)

如何派發(fā)事件(dispatchEvent)?(如何進行事件廣播?)

W3C: 使用 dispatchEvent 方法

IE: 使用 fireEvent 方法

var fireEvent = function(element, event){
    if (document.createEventObject){
        var mockEvent = document.createEventObject();
        return element.fireEvent("on" + event, mockEvent)
    }else{
        var mockEvent = document.createEvent("HTMLEvents");
        mockEvent.initEvent(event, true, true);
        return !element.dispatchEvent(mockEvent);
    }
}

什么是函數(shù)節(jié)流?介紹一下應(yīng)用場景和原理?

函數(shù)節(jié)流(throttle)是指阻止一個函數(shù)在很短時間間隔內(nèi)連續(xù)調(diào)用。

只有當上一次函數(shù)執(zhí)行后達到規(guī)定的時間間隔,才能進行下一次調(diào)用。
但要保證一個累計最小調(diào)用間隔(否則拖拽類的節(jié)流都將無連續(xù)效果)

函數(shù)節(jié)流用于 onresize, onscroll 等短時間內(nèi)會多次觸發(fā)的事件

函數(shù)節(jié)流的原理:使用定時器做時間節(jié)流。

當觸發(fā)一個事件時,先用 setTimout 讓這個事件延遲一小段時間再執(zhí)行。
如果在這個時間間隔內(nèi)又觸發(fā)了事件,就 clearTimeout 原來的定時器,
再 setTimeout 一個新的定時器重復(fù)以上流程。

函數(shù)節(jié)流簡單實現(xiàn):

function throttle(method, context) {
     clearTimeout(methor.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     }, 100); // 兩次調(diào)用至少間隔 100ms
}
// 調(diào)用
window.onresize = function(){
    throttle(myFunc, window);
}

區(qū)分什么是“客戶區(qū)坐標”、“頁面坐標”、“屏幕坐標”?

客戶區(qū)坐標:鼠標指針在可視區(qū)中的水平坐標(clientX)和垂直坐標(clientY)

頁面坐標:鼠標指針在頁面布局中的水平坐標(pageX)和垂直坐標(pageY)

屏幕坐標:設(shè)備物理屏幕的水平坐標(screenX)和垂直坐標(screenY)

如何獲得一個DOM元素的絕對位置?

elem.offsetLeft:返回元素相對于其定位父級左側(cè)的距離

elem.offsetTop:返回元素相對于其定位父級頂部的距離

elem.getBoundingClientRect():返回一個DOMRect對象,包含一組描述邊框的只讀屬性,單位像素

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

答案:[1, NaN, NaN]

parseInt(string, radix) 第2個參數(shù) radix 表示進制。省略 radix 或 radix = 0,則數(shù)字將以十進制解析

map 每次為 parseInt 傳3個參數(shù)(elem, index, array),其中 index 為數(shù)組索引

因此,map 遍歷 ["1", "2", "3"],相應(yīng) parseInt 接收參數(shù)如下

parseInt("1", 0);  // 1
parseInt("2", 1);  // NaN
parseInt("3", 2);  // NaN

所以,parseInt 參數(shù) radix 不合法,導(dǎo)致返回值為 NaN

new 操作符具體干了什么?

創(chuàng)建實例對象,this 變量引用該對象,同時還繼承了構(gòu)造函數(shù)的原型

屬性和方法被加入到 this 引用的對象中

新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this

用原生JavaScript的實現(xiàn)過什么功能嗎?

封裝選擇器、調(diào)用第三方API、設(shè)置和獲取樣式

解釋一下這段代碼的意思嗎?

  [].forEach.call($$("*"), function(el){
      el.style.outline = "1px solid #" + (~~(Math.random()*(1<<24))).toString(16);
  })

解釋:獲取頁面所有的元素,遍歷這些元素,為它們添加1像素隨機顏色的輪廓(outline)

$$(sel)// $$函數(shù)被許多現(xiàn)代瀏覽器命令行支持,等價于 document.querySelectorAll(sel)

[].forEach.call(NodeLists) // 使用 call 函數(shù)將數(shù)組遍歷函數(shù) forEach 應(yīng)到節(jié)點元素列表

el.style.outline = "1px solid #333" // 樣式 outline 位于盒模型之外,不影響元素布局位置

(1<<24) // parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 == 16777216

Math.random()*(1<<24) // 表示一個位于 0 到 16777216 之間的隨機浮點數(shù)

~~Math.random()*(1<<24) // ~~ 作用相當于 parseInt 取整

(~~(Math.random()*(1<<24))).toString(16) // 轉(zhuǎn)換為一個十六進制-

JavaScript實現(xiàn)異步編程的方法?

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

事件監(jiān)聽

發(fā)布/訂閱

Promises對象

Async函數(shù)[ES7]

web開發(fā)中會話跟蹤的方法有哪些

cookie

session

url重寫

隱藏input

ip地址

說幾條寫JavaScript的基本規(guī)范?

不要在同一行聲明多個變量

請使用 ===/!==來比較true/false或者數(shù)值

使用對象字面量替代new Array這種形式

不要使用全局函數(shù)

Switch語句必須帶有default分支

函數(shù)不應(yīng)該有時候有返回值,有時候沒有返回值

If語句必須使用大括號

for-in循環(huán)中的變量 應(yīng)該使用var關(guān)鍵字明確限定作用域,從而避免作用域污

Javascript如何實現(xiàn)繼承?

構(gòu)造繼承

原型繼承

實例繼承

拷貝繼承

原型prototype機制或apply和call方法去實現(xiàn)較簡單,建議使用構(gòu)造函數(shù)與原型混合方式

 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創(chuàng)建對象的幾種方式?

javascript創(chuàng)建對象簡單的說,無非就是使用內(nèi)置對象或各種自定義對象,當然還可以用JSON;但寫法有很多種,也能混合使用

對象字面量的方式

person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};

用function來模擬無參的構(gòu)造函數(shù)

 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();

用function來模擬參構(gòu)造函數(shù)來實現(xiàn)(用this關(guān)鍵字定義構(gòu)造的上下文屬性)

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");//實例化、創(chuàng)建對象
    maidou.eat();//調(diào)用eat方法

用工廠方式來創(chuàng)建(內(nèi)置對象)

var wcDog =new Object();
     wcDog.name="旺財";
     wcDog.age=3;
     wcDog.work=function(){
       alert("我是"+wcDog.name+",汪汪汪......");
     }
     wcDog.work();

用原型方式來創(chuàng)建

function Dog(){

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

用混合方式來創(chuàng)建

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

null,undefined 的區(qū)別?

undefined 表示不存在這個值。

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

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

null 表示一個對象被定義了,值為“空值”

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

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

在驗證null時,一定要使用 === ,因為 == 無法分別 null 和 undefined

寫一個通用的事件偵聽器函數(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;
            }
        },
        // 取消事件的默認行為
        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;
        }
    };

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

閉包是指有權(quán)訪問另一個函數(shù)作用域中變量的函數(shù),創(chuàng)建閉包的最常見的方式就是在一個函數(shù)內(nèi)創(chuàng)建另一個函數(shù),通過另一個函數(shù)訪問這個函數(shù)的局部變量,利用閉包可以突破作用鏈域

閉包的特性:

函數(shù)內(nèi)再嵌套函數(shù)

內(nèi)部函數(shù)可以引用外層的參數(shù)和變量

參數(shù)和變量不會被垃圾回收機制回收

javascript 代碼中的"use strict";是什么意思 ? 使用它區(qū)別是什么?

use strict是一種ECMAscript 5 添加的(嚴格)運行模式,這種模式使得 Javascript 在更嚴格的條件下運行,使JS編碼更加規(guī)范化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為

如何判斷一個對象是否屬于某個類?

// 使用instanceof (待完善)
   if(a instanceof Person){
       alert("yes");
   }

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

創(chuàng)建一個空對象,并且 this 變量引用該對象,同時還繼承了該函數(shù)的原型

屬性和方法被加入到 this 引用的對象中

新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this

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

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

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

Ajax 是什么? 如何創(chuàng)建一個Ajax?

ajax的全稱:Asynchronous Javascript And XML

異步傳輸+js+xml

所謂異步,在這里簡單地解釋就是:向服務(wù)器發(fā)送請求的時候,我們不必等待結(jié)果,而是可以同時做其他的事情,等到有了結(jié)果它自己會根據(jù)設(shè)定進行后續(xù)操作,與此同時,頁面是不會發(fā)生整頁刷新的,提高了用戶體驗

創(chuàng)建XMLHttpRequest對象,也就是創(chuàng)建一個異步調(diào)用對象

建一個新的HTTP請求,并指定該HTTP請求的方法、URL及驗證信息

設(shè)置響應(yīng)HTTP請求狀態(tài)變化的函數(shù)

發(fā)送HTTP請求

獲取異步調(diào)用返回的數(shù)據(jù)

用JavaScript和DOM實現(xiàn)局部刷新

同步和異步的區(qū)別?

同步:瀏覽器訪問服務(wù)器請求,用戶看得到頁面刷新,重新發(fā)請求,等請求完,頁面刷新,新內(nèi)容出現(xiàn),用戶看到新內(nèi)容,進行下一步操作

異步:瀏覽器訪問服務(wù)器請求,用戶正常操作,瀏覽器后端進行請求。等請求完,頁面不刷新,新內(nèi)容也會出現(xiàn),用戶看到新內(nèi)容

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

document.write只能重繪整個頁面

innerHTML可以重繪頁面的一部分

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

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

createDocumentFragment() //創(chuàng)建一個DOM片段

createElement() //創(chuàng)建一個具體的元素

createTextNode() //創(chuàng)建一個文本節(jié)點

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

appendChild()

removeChild()

replaceChild()

insertBefore() //在已有的子節(jié)點前插入一個新的子節(jié)點

(3)查找

getElementsByTagName() //通過標簽名稱

getElementsByName() // 通過元素的Name屬性的值(IE容錯能力較強,會得到一個數(shù)組,其中包括id等于name值的)

getElementById() //通過元素Id,唯一性

那些操作會造成內(nèi)存泄漏?

內(nèi)存泄漏指任何對象在您不再擁有或需要它之后仍然存在

垃圾回收器定期掃描對象,并計算引用了每個對象的其他對象的數(shù)量。如果一個對象的引用數(shù)量為 0(沒有其他對象引用過該對象),或?qū)υ搶ο蟮奈┮灰檬茄h(huán)的,那么該對象的內(nèi)存即可回收

setTimeout 的第一個參數(shù)使用字符串而非函數(shù)的話,會引發(fā)內(nèi)存泄漏

閉包、控制臺日志、循環(huán)(在兩個對象彼此引用且彼此保留時,就會產(chǎn)生一個循環(huán))

漸進增強和優(yōu)雅降級

漸進增強 :針對低版本瀏覽器進行構(gòu)建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果、交互等改進和追加功能達到更好的用戶體驗。

優(yōu)雅降級 :一開始就構(gòu)建完整的功能,然后再針對低版本瀏覽器進行兼容

Javascript垃圾回收方法

標記清除(mark and sweep)

這是JavaScript最常見的垃圾回收方式,當變量進入執(zhí)行環(huán)境的時候,比如函數(shù)中聲明一個變量,垃圾回收器將其標記為“進入環(huán)境”,當變量離開環(huán)境的時候(函數(shù)執(zhí)行結(jié)束)將其標記為“離開環(huán)境”

垃圾回收器會在運行的時候給存儲在內(nèi)存中的所有變量加上標記,然后去掉環(huán)境中的變量以及被環(huán)境中變量所引用的變量(閉包),在這些完成之后仍存在標記的就是要刪除的變量了

引用計數(shù)(reference counting)

在低版本IE中經(jīng)常會出現(xiàn)內(nèi)存泄露,很多時候就是因為其采用引用計數(shù)方式進行垃圾回收。引用計數(shù)的策略是跟蹤記錄每個值被使用的次數(shù),當聲明了一個 變量并將一個引用類型賦值給該變量的時候這個值的引用次數(shù)就加1,如果該變量的值變成了另外一個,則這個值得引用次數(shù)減1,當這個值的引用次數(shù)變?yōu)?的時 候,說明沒有變量在使用,這個值沒法被訪問了,因此可以將其占用的空間回收,這樣垃圾回收器會在運行的時候清理掉引用次數(shù)為0的值占用的空間

js繼承方式及其優(yōu)缺點

原型鏈繼承的缺點

一是字面量重寫原型會中斷關(guān)系,使用引用類型的原型,并且子類型還無法給超類型傳遞參數(shù)。

借用構(gòu)造函數(shù)(類式繼承)

借用構(gòu)造函數(shù)雖然解決了剛才兩種問題,但沒有原型,則復(fù)用無從談起。所以我們需要原型鏈+借用構(gòu)造函數(shù)的模式,這種模式稱為組合繼承

組合式繼承

組合式繼承是比較常用的一種繼承方法,其背后的思路是使用原型鏈實現(xiàn)對原型屬性和方法的繼承,而通過借用構(gòu)造函數(shù)來實現(xiàn)對實例屬性的繼承。這樣,既通過在原型上定義方法實現(xiàn)了函數(shù)復(fù)用,又保證每個實例都有它自己的屬性。

defer和async

defer并行加載js文件,會按照頁面上script標簽的順序執(zhí)行async并行加載js文件,下載完成立即執(zhí)行,不會按照頁面上script標簽的順序執(zhí)行

用過哪些設(shè)計模式?

工廠模式:

主要好處就是可以消除對象間的耦合,通過使用工程方法而不是new關(guān)鍵字。將所有實例化的代碼集中在一個位置防止代碼重復(fù)

工廠模式解決了重復(fù)實例化的問題 ,但還有一個問題,那就是識別問題,因為根本無法 搞清楚他們到底是哪個對象的實例

-

function createObject(name,age,profession){//集中實例化的函數(shù)var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.profession = profession;
    obj.move = function () {
        return this.name + " at " + this.age + " engaged in " + this.profession;
    };
    return obj;
}
var test1 = createObject("trigkit4",22,"programmer");//第一個實例var test2 = createObject("mike",25,"engineer");//第二個實例

構(gòu)造函數(shù)模式

使用構(gòu)造函數(shù)的方法 ,即解決了重復(fù)實例化的問題 ,又解決了對象識別的問題,該模式與工廠模式的不同之處在于

構(gòu)造函數(shù)方法沒有顯示的創(chuàng)建對象 (new Object());

直接將屬性和方法賦值給 this 對象;

沒有 renturn 語句

請解釋一下 JavaScript 的同源策略

概念:同源策略是客戶端腳本(尤其是Javascript)的重要的安全度量標準。它最早出自Netscape Navigator2.0,其目的是防止某個文檔或腳本從多個不同源裝載。這里的同源策略指的是:協(xié)議,域名,端口相同,同源策略是一種安全協(xié)議

指一段腳本只能讀取來自同一來源的窗口和文檔的屬性

為什么要有同源限制?

我們舉例說明:比如一個黑客程序,他利用Iframe把真正的銀行登錄頁面嵌到他的頁面上,當你使用真實的用戶名,密碼登錄時,他的頁面就可以通過Javascript讀取到你的表單中input中的內(nèi)容,這樣用戶名,密碼就輕松到手了。

缺點

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

實現(xiàn)一個函數(shù)clone,可以對JavaScript中的5種主要的數(shù)據(jù)類型(包括Number、String、Object、Array、Boolean)進行值復(fù)制

Object.prototype.clone = function(){

            var o = this.constructor === Array ? [] : {};

            for(var e in this){

                    o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];

            }

            return o;
    }
    

說說嚴格模式的限制

嚴格模式主要有以下限制:

變量必須聲明后再使用

函數(shù)的參數(shù)不能有同名屬性,否則報錯

不能使用with語句

不能對只讀屬性賦值,否則報錯

不能使用前綴0表示八進制數(shù),否則報錯

不能刪除不可刪除的屬性,否則報錯

不能刪除變量delete prop,會報錯,只能刪除屬性delete global[prop]

eval不會在它的外層作用域引入變量

eval和arguments不能被重新賦值

arguments不會自動反映函數(shù)參數(shù)的變化

不能使用arguments.callee

不能使用arguments.caller

禁止this指向全局對象

不能使用fn.caller和fn.arguments獲取函數(shù)調(diào)用的堆棧

增加了保留字(比如protected、static和interface)

如何刪除一個cookie

將時間設(shè)為當前時間往前一點

var date = new Date();

date.setDate(date.getDate() - 1);//真正的刪除

setDate()方法用于設(shè)置一個月的某一天

expires的設(shè)置

  document.cookie = "user="+ encodeURIComponent("name")  + ";expires = " + new Date(0)

編寫一個方法 求一個字符串的字節(jié)長度

假設(shè):一個英文字符占用一個字節(jié),一個中文字符占用兩個字節(jié)

function GetBytes(str){

        var len = str.length;

        var bytes = len;

        for(var i=0; i 255) bytes++;

        }

        return bytes;

    }

alert(GetBytes("你好,as"));

請解釋什么是事件代理

事件代理(Event Delegation),又稱之為事件委托。是 JavaScript 中常用綁定事件的常用技巧。顧名思義,“事件代理”即是把原本需要綁定的事件委托給父元素,讓父元素擔(dān)當事件監(jiān)聽的職務(wù)。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好處是可以提高性能

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

attribute是dom元素在文檔中作為html標簽擁有的屬性;

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

對于html的標準屬性來說,attribute和property是同步的,是會自動更新的

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

頁面編碼和被請求的資源編碼如果不一致如何處理?

后端響應(yīng)頭設(shè)置 charset

前端頁面設(shè)置 charset

閱讀需要支付1元查看
<