JavaScript

JavaScript的組成

  • JavaScript 由以下三部分組成:
    • ECMAScript(核心):JavaScript 語言基礎(chǔ)
    • DOM(文檔對(duì)象模型):規(guī)定了訪問HTML和XML的接口
    • BOM(瀏覽器對(duì)象模型):提供了瀏覽器窗口之間進(jìn)行交互的對(duì)象和方法

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

  • 基本數(shù)據(jù)類型:undefined礁哄、null邑狸、boolean善榛、number断箫、string趾疚、symbol
  • 引用數(shù)據(jù)類型:object、array喂很、function

檢測(cè)瀏覽器版本版本有哪些方式蚜枢?

  • 根據(jù) navigator.userAgent // UA.toLowerCase().indexOf('chrome')
  • 根據(jù) window 對(duì)象的成員 // 'ActiveXObject' in window

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

  • 數(shù)據(jù)封裝類對(duì)象:Object壶运、Array耐齐、Boolean、Number蒋情、String
  • 其他對(duì)象:Function埠况、Arguments、Math棵癣、Date辕翰、RegExp、Error
  • ES6新增對(duì)象:Symbol狈谊、Map喜命、Set、Promises河劝、Proxy壁榕、Reflect

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

  • 代碼縮進(jìn)丧裁,建議使用“四個(gè)空格”縮進(jìn)
  • 代碼段使用花括號(hào){}包裹
  • 語句結(jié)束使用分號(hào);
  • 變量和函數(shù)在使用前進(jìn)行聲明
  • 以大寫字母開頭命名構(gòu)造函數(shù),全大寫命名常量
  • 規(guī)范定義JSON對(duì)象含衔,補(bǔ)全雙引號(hào)
  • 用{}和[]聲明對(duì)象和數(shù)組

如何編寫高性能的JavaScript煎娇?

  • 遵循嚴(yán)格模式:"use strict";
  • 將js腳本放在頁面底部二庵,加快渲染頁面
  • 將js腳本將腳本成組打包,減少請(qǐng)求
  • 使用非阻塞方式下載js腳本
  • 盡量使用局部變量來保存全局變量
  • 盡量減少使用閉包
  • 使用 window 對(duì)象屬性方法時(shí)缓呛,省略 window
  • 盡量減少對(duì)象成員嵌套
  • 緩存 DOM 節(jié)點(diǎn)的訪問
  • 通過避免使用 eval() 和 Function() 構(gòu)造器
  • 給 setTimeout() 和 setInterval() 傳遞函數(shù)而不是字符串作為參數(shù)
  • 盡量使用直接量創(chuàng)建對(duì)象和數(shù)組
  • 最小化重繪(repaint)和回流(reflow)

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

  • 瀏覽器的渲染過程:

    • 解析HTML構(gòu)建 DOM(DOM樹)哟绊,并行請(qǐng)求 css/image/js
    • CSS 文件下載完成因妙,開始構(gòu)建 CSSOM(CSS樹)
    • CSSOM 構(gòu)建結(jié)束后,和 DOM 一起生成 Render Tree(渲染樹)
    • 布局(Layout):計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕中的位置
    • 顯示(Painting):通過顯卡把頁面畫到屏幕上
  • DOM樹 和 渲染樹 的區(qū)別:

    • DOM樹與HTML標(biāo)簽一一對(duì)應(yīng)票髓,包括head和隱藏元素
    • 渲染樹不包括head和隱藏元素攀涵,大段文本的每一個(gè)行都是獨(dú)立節(jié)點(diǎn),每一個(gè)節(jié)點(diǎn)都有對(duì)應(yīng)的css屬性

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

  • 重繪:當(dāng)渲染樹中的元素外觀(如:顏色)發(fā)生改變以故,不影響布局時(shí),產(chǎn)生重繪
  • 回流:當(dāng)渲染樹中的元素的布局(如:尺寸裆操、位置怒详、隱藏/狀態(tài)狀態(tài))發(fā)生改變時(shí),產(chǎn)生重繪回流
  • 注意:JS獲取Layout屬性值(如:offsetLeft踪区、scrollTop昆烁、getComputedStyle等)也會(huì)引起回流。因?yàn)闉g覽器需要通過回流計(jì)算最新值
  • 回流必將引起重繪缎岗,而重繪不一定會(huì)引起回流

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

  • 需要要對(duì)元素進(jìn)行復(fù)雜的操作時(shí),可以先隱藏(display:"none")密强,操作完成后再顯示
  • 需要?jiǎng)?chuàng)建多個(gè)DOM節(jié)點(diǎn)時(shí)茅郎,使用DocumentFragment創(chuàng)建完后一次性的加入document
  • 緩存Layout屬性值,如:var left = elem.offsetLeft; 這樣或渤,多次使用 left 只產(chǎn)生一次回流
  • 盡量避免用table布局(table元素一旦觸發(fā)回流就會(huì)導(dǎo)致table里所有的其它元素回流)
  • 避免使用css表達(dá)式(expression)系冗,因?yàn)槊看握{(diào)用都會(huì)重新計(jì)算值(包括加載頁面)
  • 盡量使用 css 屬性簡寫,如:用 border 代替 border-width, border-style, border-color
  • 批量修改元素樣式:elem.className 和 elem.style.cssText 代替 elem.style.xxx

script 的位置是否會(huì)影響首屏顯示時(shí)間薪鹦?

  • 在解析 HTML 生成 DOM 過程中掌敬,js 文件的下載是并行的,不需要 DOM 處理到 script 節(jié)點(diǎn)池磁。因此奔害,script的位置不影響首屏顯示的開始時(shí)間。
  • 瀏覽器解析 HTML 是自上而下的線性過程地熄,script作為 HTML 的一部分同樣遵循這個(gè)原則
  • 因此华临,script 會(huì)延遲 DomContentLoad,只顯示其上部分首屏內(nèi)容端考,從而影響首屏顯示的完成時(shí)間

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

  • JavaScript作用域:

    • 在Java揭厚、C等語言中,作用域?yàn)閒or語句扶供、if語句或{}內(nèi)的一塊區(qū)域筛圆,稱為作用域;
    • 而在 JavaScript 中椿浓,作用域?yàn)閒unction(){}內(nèi)的區(qū)域太援,稱為函數(shù)作用域。
  • JavaScript變量聲明提升:

    • 在JavaScript中扳碍,函數(shù)聲明與變量聲明經(jīng)常被JavaScript引擎隱式地提升到當(dāng)前作用域的頂部提岔。
    • 聲明語句中的賦值部分并不會(huì)被提升,只有名稱被提升
    • 函數(shù)聲明的優(yōu)先級(jí)高于變量左腔,如果變量名跟函數(shù)名相同且未賦值唧垦,則函數(shù)聲明會(huì)覆蓋變量聲明
    • 如果函數(shù)有多個(gè)同名參數(shù),那么最后一個(gè)參數(shù)(即使沒有定義)會(huì)覆蓋前面的同名參數(shù)

介紹JavaScript的原型液样,原型鏈振亮?有什么特點(diǎn)?

  • 原型:

    • JavaScript的所有對(duì)象中都包含了一個(gè) [proto] 內(nèi)部屬性鞭莽,這個(gè)屬性所對(duì)應(yīng)的就是該對(duì)象的原型
    • JavaScript的函數(shù)對(duì)象坊秸,除了原型 [proto] 之外,還預(yù)置了 prototype 屬性
    • 當(dāng)函數(shù)對(duì)象作為構(gòu)造函數(shù)創(chuàng)建實(shí)例時(shí)澎怒,該 prototype 屬性值將被作為實(shí)例對(duì)象的原型 [proto]褒搔。
  • 原型鏈:

    • 當(dāng)一個(gè)對(duì)象調(diào)用的屬性/方法自身不存在時(shí),就會(huì)去自己 [proto] 關(guān)聯(lián)的前輩 prototype 對(duì)象上去找
    • 如果沒找到喷面,就會(huì)去該 prototype 原型 [proto] 關(guān)聯(lián)的前輩 prototype 去找星瘾。依次類推,直到找到屬性/方法或 undefined 為止惧辈。從而形成了所謂的“原型鏈”
  • 原型特點(diǎn):
    • JavaScript對(duì)象是通過引用來傳遞的琳状,當(dāng)修改原型時(shí),與之相關(guān)的對(duì)象也會(huì)繼承這一改變

JavaScript有幾種類型的值盒齿?念逞,你能畫一下他們的內(nèi)存圖嗎

  • 原始數(shù)據(jù)類型(Undefined,Null边翁,Boolean翎承,Number、String)-- 棧
  • 引用數(shù)據(jù)類型(對(duì)象符匾、數(shù)組和函數(shù))-- 堆
  • 兩種類型的區(qū)別是:存儲(chǔ)位置不同:
  • 原始數(shù)據(jù)類型是直接存儲(chǔ)在棧(stack)中的簡單數(shù)據(jù)段叨咖,占據(jù)空間小、大小固定,屬于被頻繁使用數(shù)據(jù)甸各;
  • 引用數(shù)據(jù)類型存儲(chǔ)在堆(heap)中的對(duì)象仰剿,占據(jù)空間大、大小不固定痴晦,如果存儲(chǔ)在棧中,將會(huì)影響程序運(yùn)行的性能琳彩;
  • 引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針誊酌,該指針指向堆中該實(shí)體的起始地址。
  • 當(dāng)解釋器尋找引用值時(shí)露乏,會(huì)首先檢索其在棧中的地址碧浊,取得地址后從堆中獲得實(shí)體。

JavaScript如何實(shí)現(xiàn)一個(gè)類瘟仿,怎么實(shí)例化這個(gè)類箱锐?

  • 構(gòu)造函數(shù)法(this + prototype) -- 用 new 關(guān)鍵字 生成實(shí)例對(duì)象
    • 缺點(diǎn):用到了 this 和 prototype,編寫復(fù)雜劳较,可讀性差
  function Mobile(name, price){
     this.name = name;
     this.price = price;
   }
   Mobile.prototype.sell = function(){
      alert(this.name + "驹止,售價(jià) $" + this.price);
   }
   var iPhone7 = new Mobile("iPhone7", 1000);
   iPhone7.sell();
  • Object.create 法 -- 用 Object.create() 生成實(shí)例對(duì)象
  • 缺點(diǎn):不能實(shí)現(xiàn)私有屬性和私有方法,實(shí)例對(duì)象之間也不能共享數(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() 得到實(shí)例對(duì)象
    • 優(yōu)點(diǎn):容易理解臊恋,結(jié)構(gòu)清晰優(yōu)雅,符合傳統(tǒng)的"面向?qū)ο缶幊?的構(gòu)造
 var Cat = {
   age: 3, // 共享數(shù)據(jù) -- 定義在類對(duì)象內(nèi)墓捻,createNew() 外
   createNew: function () {
     var cat = {};
     // var cat = Animal.createNew(); // 繼承 Animal 類
     cat.name = "小咪";
     var sound = "喵喵喵"; // 私有屬性--定義在 createNew() 內(nèi)抖仅,輸出對(duì)象外
     cat.makeSound = function () {
       alert(sound);  // 暴露私有屬性
     };
     cat.changeAge = function(num){
       Cat.age = num; // 修改共享數(shù)據(jù)
     };
     return cat; // 輸出對(duì)象
   }
 };

 var cat = Cat.createNew();
 cat.makeSound();
  • ES6 語法糖 class -- 用 new 關(guān)鍵字 生成實(shí)例對(duì)象
     class Point {
       constructor(x, y) {
         this.x = x;
         this.y = y;
       }
       toString() {
         return '(' + this.x + ', ' + this.y + ')';
       }
     }

  var point = new Point(2, 3);

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

  • 構(gòu)造函數(shù)綁定:使用 call 或 apply 方法砖第,將父對(duì)象的構(gòu)造函數(shù)綁定在子對(duì)象上
function Cat(name,color){
  Animal.apply(this, arguments);
  this.name = name;
  this.color = color;
}
  • 實(shí)例繼承:將子對(duì)象的 prototype 指向父對(duì)象的一個(gè)實(shí)例
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
  • 拷貝繼承:如果把父對(duì)象的所有屬性和方法撤卢,拷貝進(jìn)子對(duì)象
    function extend(Child, Parent) {
     var p = Parent.prototype;
     var c = Child.prototype;
     for (var i in p) {
        c[i] = p[i];
     }
     c.uber = p;
    }
  • 原型繼承:將子對(duì)象的 prototype 指向父對(duì)象的 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()
       }
    }

Javascript作用鏈域?

  • 全局函數(shù)無法查看局部函數(shù)的內(nèi)部細(xì)節(jié),但局部函數(shù)可以查看其上層的函數(shù)細(xì)節(jié)梧兼,直至全局細(xì)節(jié)
  • 如果當(dāng)前作用域沒有找到屬性或方法放吩,會(huì)向上層作用域查找,直至全局函數(shù)袱院,這種形式就是作用域鏈

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

  • this 總是指向函數(shù)的直接調(diào)用者
  • 如果有 new 關(guān)鍵字屎慢,this 指向 new 出來的實(shí)例對(duì)象
  • 在事件中,this指向觸發(fā)這個(gè)事件的對(duì)象
  • IE下 attachEvent 中的this總是指向全局對(duì)象Window

eval是做什么的忽洛?

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

  • 應(yīng)該避免使用eval腻惠,不安全,非常耗性能(先解析成js語句欲虚,再執(zhí)行)
  • 由JSON字符串轉(zhuǎn)換為JSON對(duì)象的時(shí)候可以用 eval('('+ str +')');

什么是 Window 對(duì)象? 什么是 Document 對(duì)象?

  • Window 對(duì)象表示當(dāng)前瀏覽器的窗口集灌,是JavaScript的頂級(jí)對(duì)象。
  • 我們創(chuàng)建的所有對(duì)象、函數(shù)欣喧、變量都是 Window 對(duì)象的成員腌零。
  • Window 對(duì)象的方法和屬性是在全局范圍內(nèi)有效的。
  • Document 對(duì)象是 HTML 文檔的根節(jié)點(diǎn)與所有其他節(jié)點(diǎn)(元素節(jié)點(diǎn)唆阿,文本節(jié)點(diǎn)益涧,屬性節(jié)點(diǎn), 注釋節(jié)點(diǎn))
  • Document 對(duì)象使我們可以通過腳本對(duì) HTML 頁面中的所有元素進(jìn)行訪問
  • Document 對(duì)象是 Window 對(duì)象的一部分,可通過 window.document 屬性對(duì)其進(jìn)行訪問

介紹 DOM 的發(fā)展

  • DOM:文檔對(duì)象模型(Document Object Model)驯鳖,定義了訪問HTML和XML文檔的標(biāo)準(zhǔn)闲询,與編程語言及平臺(tái)無關(guān)
  • DOM0:提供了查詢和操作Web文檔的內(nèi)容API。未形成標(biāo)準(zhǔn)浅辙,實(shí)現(xiàn)混亂扭弧。如:document.forms['login']
  • DOM1:W3C提出標(biāo)準(zhǔn)化的DOM,簡化了對(duì)文檔中任意部分的訪問和操作记舆。如:JavaScript中的Document對(duì)象
  • DOM2:原來DOM基礎(chǔ)上擴(kuò)充了鼠標(biāo)事件等細(xì)分模塊鸽捻,增加了對(duì)CSS的支持。如:getComputedStyle(elem, pseudo)
  • DOM3:增加了XPath模塊和加載與保存(Load and Save)模塊泽腮。如:XPathEvaluator

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

  • DOM0級(jí)事件處理方式:
    • btn.onclick = func;
    • btn.onclick = null;
  • DOM2級(jí)事件處理方式:
    • btn.addEventListener('click', func, false);
    • btn.removeEventListener('click', func, false);
    • btn.attachEvent("onclick", func);
    • btn.detachEvent("onclick", func);
  • DOM3級(jí)事件處理方式:
    • eventUtil.addListener(input, "textInput", func);
    • eventUtil 是自定義對(duì)象诊赊,textInput 是DOM3級(jí)事件

事件的三個(gè)階段

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

介紹事件“捕獲”和“冒泡”執(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í)行冒泡

事件的代理/委托

  • 事件委托是指將事件綁定目標(biāo)元素的到父元素上,利用冒泡機(jī)制觸發(fā)該事件
    • 優(yōu)點(diǎn):
      • 可以減少事件注冊(cè)惭每,節(jié)省大量內(nèi)存占用
      • 可以將事件應(yīng)用于動(dòng)態(tài)添加的子元素上
    • 缺點(diǎn):
      使用不當(dāng)會(huì)造成事件在不應(yīng)該觸發(fā)時(shí)觸發(fā)
    • 示例:
ulEl.addEventListener('click', function(e){
    var target = event.target || event.srcElement;
    if(!!target && target.nodeName.toUpperCase() === "LI"){
        console.log(target.innerHTML);
    }
}, false);

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

  • IE只事件冒泡,不支持事件捕獲宏赘;火狐同時(shí)支持件冒泡和事件捕獲

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);
  • 事件對(duì)象

    • W3C: var e = arguments.callee.caller.arguments[0]
    • IE: window.event
  • 事件目標(biāo)

    • W3C: e.target
    • IE: window.event.srcElement
  • 阻止事件默認(rèn)行為

    • W3C: window.event.cancelBubble = true
    • IE: window.event.returnValue = false
  • 阻止事件傳播

    • W3C: e.stopPropagation()
    • IE: window.event

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

  • target 只會(huì)出現(xiàn)在事件流的目標(biāo)階段
  • currentTarget 可能出現(xiàn)在事件流的任何階段
  • 當(dāng)事件流處在目標(biāo)階段時(shí)察署,二者的指向相同
  • 當(dāng)事件流處于捕獲或冒泡階段時(shí):currentTarget 指向當(dāng)前事件活動(dòng)的對(duì)象(一般為父級(jí))

如何派發(fā)事件(dispatchEvent)闷游?(如何進(jìn)行事件廣播幻枉?)

  • 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)用場(chǎng)景和原理?

  • 函數(shù)節(jié)流(throttle)是指阻止一個(gè)函數(shù)在很短時(shí)間間隔內(nèi)連續(xù)調(diào)用误阻。
    只有當(dāng)上一次函數(shù)執(zhí)行后達(dá)到規(guī)定的時(shí)間間隔嘶是,才能進(jìn)行下一次調(diào)用。
    但要保證一個(gè)累計(jì)最小調(diào)用間隔(否則拖拽類的節(jié)流都將無連續(xù)效果)

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

  • 函數(shù)節(jié)流的原理:使用定時(shí)器做時(shí)間節(jié)流蛛碌。
    當(dāng)觸發(fā)一個(gè)事件時(shí)聂喇,先用 setTimout 讓這個(gè)事件延遲一小段時(shí)間再執(zhí)行。
    如果在這個(gè)時(shí)間間隔內(nèi)又觸發(fā)了事件蔚携,就 clearTimeout 原來的定時(shí)器希太,
    再 setTimeout 一個(gè)新的定時(shí)器重復(fù)以上流程。

  • 函數(shù)節(jié)流簡單實(shí)現(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ū)坐標(biāo)”誊辉、“頁面坐標(biāo)”、“屏幕坐標(biāo)”亡脑?

  • 客戶區(qū)坐標(biāo):鼠標(biāo)指針在可視區(qū)中的水平坐標(biāo)(clientX)和垂直坐標(biāo)(clientY)
  • 頁面坐標(biāo):鼠標(biāo)指針在頁面布局中的水平坐標(biāo)(pageX)和垂直坐標(biāo)(pageY)
  • 屏幕坐標(biāo):設(shè)備物理屏幕的水平坐標(biāo)(screenX)和垂直坐標(biāo)(screenY)

如何獲得一個(gè)DOM元素的絕對(duì)位置堕澄?

  • elem.offsetLeft:返回元素相對(duì)于其定位父級(jí)左側(cè)的距離
  • elem.offsetTop:返回元素相對(duì)于其定位父級(jí)頂部的距離
  • elem.getBoundingClientRect():返回一個(gè)DOMRect對(duì)象,包含一組描述邊框的只讀屬性霉咨,單位像素

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

  • 答案:[1, NaN, NaN]
  • parseInt(string, radix) 第2個(gè)參數(shù) radix 表示進(jìn)制。省略 radix 或 radix = 0途戒,則數(shù)字將以十進(jìn)制解析
  • map 每次為 parseInt 傳3個(gè)參數(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)建實(shí)例對(duì)象浆西,this 變量引用該對(duì)象,同時(shí)還繼承了構(gòu)造函數(shù)的原型
  • 屬性和方法被加入到 this 引用的對(duì)象中
  • 新創(chuàng)建的對(duì)象由 this 所引用顽腾,并且最后隱式的返回 this

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

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

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

  [].forEach.call($$("*"), function(el){
      el.style.outline = "1px solid #" + (~~(Math.random()*(1<<24))).toString(16);
  })
  • 解釋:獲取頁面所有的元素猪瞬,遍歷這些元素,為它們添加1像素隨機(jī)顏色的輪廓(outline)
    1. $$(sel) // $$函數(shù)被許多現(xiàn)代瀏覽器命令行支持入篮,等價(jià)于 document.querySelectorAll(sel)
    1. [].forEach.call(NodeLists) // 使用 call 函數(shù)將數(shù)組遍歷函數(shù) forEach 應(yīng)到節(jié)點(diǎn)元素列表
    1. el.style.outline = "1px solid #333" // 樣式 outline 位于盒模型之外陈瘦,不影響元素布局位置
    1. (1<<24) // parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 == 16777216
    1. Math.random()*(1<<24) // 表示一個(gè)位于 0 到 16777216 之間的隨機(jī)浮點(diǎn)數(shù)
    1. ~~Math.random()*(1<<24) // ~~ 作用相當(dāng)于 parseInt 取整
    1. (~~(Math.random()*(1<<24))).toString(16) // 轉(zhuǎn)換為一個(gè)十六進(jìn)制-

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

  • 回調(diào)函數(shù)
  • 事件監(jiān)聽
  • 發(fā)布/訂閱
  • Promises對(duì)象
  • Async函數(shù)[ES7]

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

  • cookie
  • session
  • url重寫
  • 隱藏input
  • ip地址

介紹js的基本數(shù)據(jù)類型

  • Undefined潮售、Null痊项、Boolean、Number酥诽、String

介紹js有哪些內(nèi)置對(duì)象鞍泉?

  • Object 是 JavaScript 中所有對(duì)象的父對(duì)象
  • 數(shù)據(jù)封裝類對(duì)象:Object、Array肮帐、Boolean咖驮、Number 和 String
  • 其他對(duì)象:Function、Arguments训枢、Math托修、Date、RegExp恒界、Error

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

  • 不要在同一行聲明多個(gè)變量
  • 請(qǐng)使用 ===/!==來比較true/false或者數(shù)值
  • 使用對(duì)象字面量替代new Array這種形式
  • 不要使用全局函數(shù)
  • Switch語句必須帶有default分支
  • 函數(shù)不應(yīng)該有時(shí)候有返回值,有時(shí)候沒有返回值
  • If語句必須使用大括號(hào)
  • for-in循環(huán)中的變量 應(yīng)該使用var關(guān)鍵字明確限定作用域十酣,從而避免作用域污

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

  • 每個(gè)對(duì)象都會(huì)在其內(nèi)部初始化一個(gè)屬性耸采,就是prototype(原型)吃环,當(dāng)我們?cè)L問一個(gè)對(duì)象的屬性時(shí)

  • 如果這個(gè)對(duì)象內(nèi)部不存在這個(gè)屬性,那么他就會(huì)去prototype里找這個(gè)屬性洋幻,這個(gè)prototype又會(huì)有自己的prototype郁轻,于是就這樣一直找下去,也就是我們平時(shí)所說的原型鏈的概念

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

  • 特點(diǎn):

    • JavaScript對(duì)象是通過引用來傳遞的文留,我們創(chuàng)建的每個(gè)新對(duì)象實(shí)體中并沒有一份屬于自己的原型副本好唯。當(dāng)我們修改原型時(shí),與之相關(guān)的對(duì)象也會(huì)繼承這一改變燥翅。
  • 當(dāng)我們需要一個(gè)屬性的時(shí)骑篙,Javascript引擎會(huì)先看當(dāng)前對(duì)象中是否有這個(gè)屬性, 如果沒有的

  • 就會(huì)查找他的Prototype對(duì)象是否有這個(gè)屬性森书,如此遞推下去靶端,一直檢索到 Object 內(nèi)建對(duì)象

JavaScript有幾種類型的值谎势?,你能畫一下他們的內(nèi)存圖嗎杨名?

  • 棧:原始數(shù)據(jù)類型(Undefined脏榆,Null,Boolean台谍,Number须喂、String)

  • 堆:引用數(shù)據(jù)類型(對(duì)象、數(shù)組和函數(shù))

  • 兩種類型的區(qū)別是:存儲(chǔ)位置不同趁蕊;

  • 原始數(shù)據(jù)類型直接存儲(chǔ)在棧(stack)中的簡單數(shù)據(jù)段坞生,占據(jù)空間小、大小固定掷伙,屬于被頻繁使用數(shù)據(jù)是己,所以放入棧中存儲(chǔ);

  • 引用數(shù)據(jù)類型存儲(chǔ)在堆(heap)中的對(duì)象,占據(jù)空間大任柜、大小不固定,如果存儲(chǔ)在棧中卒废,將會(huì)影響程序運(yùn)行的性能;引用數(shù)據(jù)類型在棧中存儲(chǔ)了指針乘盼,該指針指向堆中該實(shí)體的起始地址。當(dāng)解釋器尋找引用值時(shí)俄烁,會(huì)首先檢索其

  • 在棧中的地址绸栅,取得地址后從堆中獲得實(shí)體

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

  • 構(gòu)造繼承

  • 原型繼承

  • 實(shí)例繼承

  • 拷貝繼承

  • 原型prototype機(jī)制或apply和call方法去實(shí)現(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)建對(duì)象的幾種方式?

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

  • 對(duì)象字面量的方式
person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  • 用function來模擬無參的構(gòu)造函數(shù)
 function Person(){}
    var person=new Person();//定義一個(gè)function牢贸,如果使用new"實(shí)例化",該function可以看作是一個(gè)Class
        person.name="Mark";
        person.age="25";
        person.work=function(){
        alert(person.name+" hello...");
    }
person.work();
  • 用function來模擬參構(gòu)造函數(shù)來實(shí)現(xiàn)(用this關(guān)鍵字定義構(gòu)造的上下文屬性)
function Pet(name,age,hobby){
       this.name=name;//this作用域:當(dāng)前對(duì)象
       this.age=age;
       this.hobby=hobby;
       this.eat=function(){
          alert("我叫"+this.name+",我喜歡"+this.hobby+",是個(gè)程序員");
       }
    }
    var maidou =new Pet("麥兜",25,"coding");//實(shí)例化竹观、創(chuàng)建對(duì)象
    maidou.eat();//調(diào)用eat方法
  • 用工廠方式來創(chuàng)建(內(nèi)置對(duì)象)
var wcDog =new Object();
     wcDog.name="旺財(cái)";
     wcDog.age=3;
     wcDog.work=function(){
       alert("我是"+wcDog.name+",汪汪汪......");
     }
     wcDog.work();
  • 用原型方式來創(chuàng)建
function Dog(){

     }
     Dog.prototype.name="旺財(cái)";
     Dog.prototype.eat=function(){
     alert(this.name+"是個(gè)吃貨");
     }
     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(); 

Javascript作用鏈域?

  • 全局函數(shù)無法查看局部函數(shù)的內(nèi)部細(xì)節(jié)潜索,但局部函數(shù)可以查看其上層的函數(shù)細(xì)節(jié)臭增,直至全局細(xì)節(jié)
  • 當(dāng)需要從局部函數(shù)查找某一屬性或方法時(shí),如果當(dāng)前作用域沒有找到竹习,就會(huì)上溯到上層作用域查找
  • 直至全局函數(shù)誊抛,這種組織形式就是作用域鏈

談?wù)凾his對(duì)象的理解

  • this總是指向函數(shù)的直接調(diào)用者(而非間接調(diào)用者)
  • 如果有new關(guān)鍵字,this指向new出來的那個(gè)對(duì)象
  • 在事件中整陌,this指向觸發(fā)這個(gè)事件的對(duì)象拗窃,特殊的是瞎领,IE中的attachEvent中的this總是指向全局對(duì)象Window

eval是做什么的?

  • 它的功能是把對(duì)應(yīng)的字符串解析成JS代碼并運(yùn)行
  • 應(yīng)該避免使用eval随夸,不安全九默,非常耗性能(2次,一次解析成js語句逃魄,一次執(zhí)行)
  • 由JSON字符串轉(zhuǎn)換為JSON對(duì)象的時(shí)候可以用eval荤西,var obj =eval('('+ str +')')

null,undefined 的區(qū)別伍俘?

  • undefined 表示不存在這個(gè)值邪锌。

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

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

  • null 表示一個(gè)對(duì)象被定義了妇萄,值為“空值”

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

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

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

寫一個(gè)通用的事件偵聽器函數(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;
            }
        },
        // 阻止事件 (主要是事件冒泡罕扎,因?yàn)镮E不支持事件捕獲)
        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對(duì)象的引用聚唐,取到事件的所有信息,確保隨時(shí)能使用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] 因?yàn)?parseInt 需要兩個(gè)參數(shù) (val, radix),其中 radix 表示解析時(shí)用的基數(shù)臀蛛。
  • map 傳了 3 個(gè) (element, index, array)亲桦,對(duì)應(yīng)的 radix 不合法導(dǎo)致解析失敗。

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

  • 我們?cè)诰W(wǎng)頁中的某個(gè)操作(有的操作對(duì)應(yīng)多個(gè)事件)氧卧。例如:當(dāng)我們點(diǎn)擊一個(gè)按鈕就會(huì)產(chǎn)生一個(gè)事件桃笙。是可以被 JavaScript 偵測(cè)到的行為
  • 事件處理機(jī)制:IE是事件冒泡、Firefox同時(shí)支持兩種事件模型沙绝,也就是:捕獲型事件和冒泡型事件
  • ev.stopPropagation();(舊ie的方法 ev.cancelBubble = true;)

什么是閉包(closure)搏明,為什么要用它鼠锈?

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

  • 閉包的特性:

    • 函數(shù)內(nèi)再嵌套函數(shù)
    • 內(nèi)部函數(shù)可以引用外層的參數(shù)和變量
    • 參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收

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

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

如何判斷一個(gè)對(duì)象是否屬于某個(gè)類同欠?

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

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

  • 創(chuàng)建一個(gè)空對(duì)象,并且 this 變量引用該對(duì)象横缔,同時(shí)還繼承了該函數(shù)的原型
  • 屬性和方法被加入到 this 引用的對(duì)象中
  • 新創(chuàng)建的對(duì)象由 this 所引用铺遂,并且最后隱式的返回 this
var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

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

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

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

ajax的全稱:Asynchronous Javascript And XML

  • 異步傳輸+js+xml

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

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

  • 建一個(gè)新的HTTP請(qǐng)求,并指定該HTTP請(qǐng)求的方法筝闹、URL及驗(yàn)證信息

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

  • 發(fā)送HTTP請(qǐng)求

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

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

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

  • 同步:瀏覽器訪問服務(wù)器請(qǐng)求,用戶看得到頁面刷新俊马,重新發(fā)請(qǐng)求,等請(qǐng)求完丁存,頁面刷新肩杈,新內(nèi)容出現(xiàn)柴我,用戶看到新內(nèi)容,進(jìn)行下一步操作
  • 異步:瀏覽器訪問服務(wù)器請(qǐng)求,用戶正常操作扩然,瀏覽器后端進(jìn)行請(qǐng)求艘儒。等請(qǐng)求完,頁面不刷新夫偶,新內(nèi)容也會(huì)出現(xiàn)界睁,用戶看到新內(nèi)容

異步加載JS的方式有哪些?

  • defer兵拢,只支持IE
  • async:
  • 創(chuàng)建script翻斟,插入到DOM中,加載完畢后callBack

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

  • document.write只能重繪整個(gè)頁面
  • innerHTML可以重繪頁面的一部分

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,唯一性

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

  • 內(nèi)存泄漏指任何對(duì)象在您不再擁有或需要它之后仍然存在
  • 垃圾回收器定期掃描對(duì)象配并,并計(jì)算引用了每個(gè)對(duì)象的其他對(duì)象的數(shù)量。如果一個(gè)對(duì)象的引用數(shù)量為 0(沒有其他對(duì)象引用過該對(duì)象)霍转,或?qū)υ搶?duì)象的惟一引用是循環(huán)的荐绝,那么該對(duì)象的內(nèi)存即可回收
  • setTimeout 的第一個(gè)參數(shù)使用字符串而非函數(shù)的話,會(huì)引發(fā)內(nèi)存泄漏
  • 閉包避消、控制臺(tái)日志低滩、循環(huán)(在兩個(gè)對(duì)象彼此引用且彼此保留時(shí),就會(huì)產(chǎn)生一個(gè)循環(huán))

漸進(jìn)增強(qiáng)和優(yōu)雅降級(jí)

  • 漸進(jìn)增強(qiáng) :針對(duì)低版本瀏覽器進(jìn)行構(gòu)建頁面岩喷,保證最基本的功能恕沫,然后再針對(duì)高級(jí)瀏覽器進(jìn)行效果、交互等改進(jìn)和追加功能達(dá)到更好的用戶體驗(yàn)纱意。

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

Javascript垃圾回收方法

  • 標(biāo)記清除(mark and sweep)
  • 這是JavaScript最常見的垃圾回收方式,當(dāng)變量進(jìn)入執(zhí)行環(huán)境的時(shí)候偷霉,比如函數(shù)中聲明一個(gè)變量迄委,垃圾回收器將其標(biāo)記為“進(jìn)入環(huán)境”,當(dāng)變量離開環(huán)境的時(shí)候(函數(shù)執(zhí)行結(jié)束)將其標(biāo)記為“離開環(huán)境”
  • 垃圾回收器會(huì)在運(yùn)行的時(shí)候給存儲(chǔ)在內(nèi)存中的所有變量加上標(biāo)記类少,然后去掉環(huán)境中的變量以及被環(huán)境中變量所引用的變量(閉包)叙身,在這些完成之后仍存在標(biāo)記的就是要?jiǎng)h除的變量了

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

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

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

  • 原型鏈繼承的缺點(diǎn)

    • 一是字面量重寫原型會(huì)中斷關(guān)系活尊,使用引用類型的原型隶校,并且子類型還無法給超類型傳遞參數(shù)琼蚯。
  • 借用構(gòu)造函數(shù)(類式繼承)

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

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

defer和async

  • defer并行加載js文件攘蔽,會(huì)按照頁面上script標(biāo)簽的順序執(zhí)行async并行加載js文件龙屉,下載完成立即執(zhí)行,不會(huì)按照頁面上script標(biāo)簽的順序執(zhí)行

用過哪些設(shè)計(jì)模式满俗?

  • 工廠模式:
    • 主要好處就是可以消除對(duì)象間的耦合转捕,通過使用工程方法而不是new關(guān)鍵字。將所有實(shí)例化的代碼集中在一個(gè)位置防止代碼重復(fù)
    • 工廠模式解決了重復(fù)實(shí)例化的問題 唆垃,但還有一個(gè)問題,那就是識(shí)別問題五芝,因?yàn)楦緹o法 搞清楚他們到底是哪個(gè)對(duì)象的實(shí)例
function createObject(name,age,profession){//集中實(shí)例化的函數(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');//第一個(gè)實(shí)例var test2 = createObject('mike',25,'engineer');//第二個(gè)實(shí)例

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

    • 使用構(gòu)造函數(shù)的方法 ,即解決了重復(fù)實(shí)例化的問題 辕万,又解決了對(duì)象識(shí)別的問題枢步,該模式與工廠模式的不同之處在于
  • 構(gòu)造函數(shù)方法沒有顯示的創(chuàng)建對(duì)象 (new Object());

  • 直接將屬性和方法賦值給 this 對(duì)象;

  • 沒有 renturn 語句

說說你對(duì)閉包的理解

  • 使用閉包主要是為了設(shè)計(jì)私有的方法和變量。閉包的優(yōu)點(diǎn)是可以避免全局變量的污染渐尿,缺點(diǎn)是閉包會(huì)常駐內(nèi)存醉途,會(huì)增大內(nèi)存使用量,使用不當(dāng)很容易造成內(nèi)存泄露砖茸。在js中隘擎,函數(shù)即閉包,只有函數(shù)才會(huì)產(chǎn)生作用域的概念

  • 閉包有三個(gè)特性:

    • 1.函數(shù)嵌套函數(shù)

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

    • 3.參數(shù)和變量不會(huì)被垃圾回收機(jī)制回收

請(qǐng)解釋一下 JavaScript 的同源策略

  • 概念:同源策略是客戶端腳本(尤其是Javascript)的重要的安全度量標(biāo)準(zhǔn)渔彰。它最早出自Netscape Navigator2.0嵌屎,其目的是防止某個(gè)文檔或腳本從多個(gè)不同源裝載推正。這里的同源策略指的是:協(xié)議恍涂,域名,端口相同植榕,同源策略是一種安全協(xié)議
  • 指一段腳本只能讀取來自同一來源的窗口和文檔的屬性

為什么要有同源限制再沧?

  • 我們舉例說明:比如一個(gè)黑客程序,他利用Iframe把真正的銀行登錄頁面嵌到他的頁面上尊残,當(dāng)你使用真實(shí)的用戶名炒瘸,密碼登錄時(shí)淤堵,他的頁面就可以通過Javascript讀取到你的表單中input中的內(nèi)容,這樣用戶名顷扩,密碼就輕松到手了拐邪。
  • 缺點(diǎn)
    • 現(xiàn)在網(wǎng)站的JS都會(huì)進(jìn)行壓縮,一些文件用了嚴(yán)格模式隘截,而另一些沒有扎阶。這時(shí)這些本來是嚴(yán)格模式的文件,被 merge后婶芭,這個(gè)串就到了文件的中間东臀,不僅沒有指示嚴(yán)格模式,反而在壓縮后浪費(fèi)了字節(jié)

實(shí)現(xiàn)一個(gè)函數(shù)clone犀农,可以對(duì)JavaScript中的5種主要的數(shù)據(jù)類型(包括Number惰赋、String、Object呵哨、Array赁濒、Boolean)進(jìn)行值復(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;
    }
    

說說嚴(yán)格模式的限制

  • 嚴(yán)格模式主要有以下限制:

  • 變量必須聲明后再使用

  • 函數(shù)的參數(shù)不能有同名屬性,否則報(bào)錯(cuò)

  • 不能使用with語句

  • 不能對(duì)只讀屬性賦值孟害,否則報(bào)錯(cuò)

  • 不能使用前綴0表示八進(jìn)制數(shù)流部,否則報(bào)錯(cuò)

  • 不能刪除不可刪除的屬性,否則報(bào)錯(cuò)

  • 不能刪除變量delete prop纹坐,會(huì)報(bào)錯(cuò)枝冀,只能刪除屬性delete global[prop]

  • eval不會(huì)在它的外層作用域引入變量

  • eval和arguments不能被重新賦值

  • arguments不會(huì)自動(dòng)反映函數(shù)參數(shù)的變化

  • 不能使用arguments.callee

  • 不能使用arguments.caller

  • 禁止this指向全局對(duì)象

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

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

如何刪除一個(gè)cookie

  • 將時(shí)間設(shè)為當(dāng)前時(shí)間往前一點(diǎn)
var date = new Date();

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

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

  • expires的設(shè)置
  document.cookie = 'user='+ encodeURIComponent('name')  + ';expires = ' + new Date(0)

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

  • 假設(shè):一個(gè)英文字符占用一個(gè)字節(jié)耘子,一個(gè)中文字符占用兩個(gè)字節(jié)
function GetBytes(str){

        var len = str.length;

        var bytes = len;

        for(var i=0; i<len; i++){

            if (str.charCodeAt(i) > 255) bytes++;

        }

        return bytes;

    }

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

請(qǐng)解釋什么是事件代理

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

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

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

  • property就是dom元素在js中作為對(duì)象擁有的屬性庐镐。

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

  • 但是對(duì)于自定義的屬性來說必逆,他們是不同步的

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

  • 后端響應(yīng)頭設(shè)置 charset
  • 前端頁面<meta>設(shè)置 charset

<script>放在</body>之前和之后有什么區(qū)別?瀏覽器會(huì)如何解析它們名眉?

  • 按照HTML標(biāo)準(zhǔn)粟矿,在</body>結(jié)束后出現(xiàn)<script>或任何元素的開始標(biāo)簽,都是解析錯(cuò)誤
  • 雖然不符合HTML標(biāo)準(zhǔn)损拢,但瀏覽器會(huì)自動(dòng)容錯(cuò)陌粹,使實(shí)際效果與寫在</body>之前沒有區(qū)別
  • 瀏覽器的容錯(cuò)機(jī)制會(huì)忽略<script>之前的</body>,視作<script>仍在 body 體內(nèi)福压。省略</body></html>閉合標(biāo)簽符合HTML標(biāo)準(zhǔn)申屹,服務(wù)器可以利用這一標(biāo)準(zhǔn)盡可能少輸出內(nèi)容

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

  • 設(shè)置<script>屬性 defer="defer" (腳本將在頁面完成解析時(shí)執(zhí)行)
  • 動(dòng)態(tài)創(chuàng)建 script DOM:document.createElement('script');
  • XmlHttpRequest 腳本注入
  • 延遲加載工具 LazyLoad

異步加載JS的方式有哪些隧膏?

  • 設(shè)置<script>屬性 async="async" (一旦腳本可用哗讥,則會(huì)異步執(zhí)行)
  • 動(dòng)態(tài)創(chuàng)建 script DOM:document.createElement('script');
  • XmlHttpRequest 腳本注入
  • 異步加載庫 LABjs
  • 模塊加載器 Sea.js

JavaScript 中,調(diào)用函數(shù)有哪幾種方式胞枕?

  • 方法調(diào)用模式 Foo.foo(arg1, arg2);
  • 函數(shù)調(diào)用模式 foo(arg1, arg2);
  • 構(gòu)造器調(diào)用模式 (new Foo())(arg1, arg2);
  • call/applay調(diào)用模式 Foo.foo.call(that, arg1, arg2);
  • bind調(diào)用模式 Foo.foo.bind(that)(arg1, arg2)();

簡單實(shí)現(xiàn) Function.bind 函數(shù)杆煞?

  if (!Function.prototype.bind) {
    Function.prototype.bind = function(that) {
      var func = this, args = arguments;
      return function() {
        return func.apply(that, Array.prototype.slice.call(args, 1));
      }
    }
  }
  // 只支持 bind 階段的默認(rèn)參數(shù):
  func.bind(that, arg1, arg2)();

  // 不支持以下調(diào)用階段傳入的參數(shù):
  func.bind(that)(arg1, arg2);

** 列舉一下JavaScript數(shù)組和對(duì)象有哪些原生方法?**

  • 數(shù)組:

    • arr.concat(arr1, arr2, arrn);
    • arr.join(",");
    • arr.sort(func);
    • arr.pop();
    • arr.push(e1, e2, en);
    • arr.shift();
    • unshift(e1, e2, en);
    • arr.reverse();
    • arr.slice(start, end);
    • arr.splice(index, count, e1, e2, en);
    • arr.indexOf(el);
    • arr.includes(el); // ES6
  • 對(duì)象:

    • object.hasOwnProperty(prop);
    • object.propertyIsEnumerable(prop);
    • object.valueOf();
    • object.toString();
    • object.toLocaleString();
    • Class.prototype.isPropertyOf(object);

Array.splice() 與 Array.splice() 的區(qū)別腐泻?

  • slice -- “讀取”數(shù)組指定的元素决乎,不會(huì)對(duì)原數(shù)組進(jìn)行修改

    • 語法:arr.slice(start, end)
    • start 指定選取開始位置(含)
    • end 指定選取結(jié)束位置(不含)
  • splice

    • “操作”數(shù)組指定的元素,會(huì)修改原數(shù)組派桩,返回被刪除的元素
    • 語法:arr.splice(index, count, [insert Elements])
    • index 是操作的起始位置
    • count = 0 插入元素构诚,count > 0 刪除元素
    • [insert Elements] 向數(shù)組新插入的元素

JavaScript 對(duì)象生命周期的理解?

  • 當(dāng)創(chuàng)建一個(gè)對(duì)象時(shí)铆惑,JavaScript 會(huì)自動(dòng)為該對(duì)象分配適當(dāng)?shù)膬?nèi)存
  • 垃圾回收器定期掃描對(duì)象范嘱,并計(jì)算引用了該對(duì)象的其他對(duì)象的數(shù)量
  • 如果被引用數(shù)量為 0,或惟一引用是循環(huán)的员魏,那么該對(duì)象的內(nèi)存即可回收

哪些操作會(huì)造成內(nèi)存泄漏丑蛤?

  • JavaScript 內(nèi)存泄露指對(duì)象在不需要使用它時(shí)仍然存在,導(dǎo)致占用的內(nèi)存不能使用或回收

  • 未使用 var 聲明的全局變量

  • 閉包函數(shù)(Closures)

  • 循環(huán)引用(兩個(gè)對(duì)象相互引用)

  • 控制臺(tái)日志(console.log)

  • 移除存在綁定事件的DOM元素(IE)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撕阎,一起剝皮案震驚了整個(gè)濱河市受裹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌虏束,老刑警劉巖棉饶,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異镇匀,居然都是意外死亡照藻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門坑律,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岩梳,“玉大人,你說我怎么就攤上這事晃择〖街担” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵宫屠,是天一觀的道長列疗。 經(jīng)常有香客問我,道長浪蹂,這世上最難降的妖魔是什么抵栈? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坤次,結(jié)果婚禮上古劲,老公的妹妹穿的比我還像新娘。我一直安慰自己缰猴,他們只是感情好产艾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滑绒,像睡著了一般闷堡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疑故,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天杠览,我揣著相機(jī)與錄音,去河邊找鬼纵势。 笑死踱阿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的钦铁。 我是一名探鬼主播扫茅,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼育瓜!你這毒婦竟也來了葫隙?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤躏仇,失蹤者是張志新(化名)和其女友劉穎恋脚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體焰手,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡糟描,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了书妻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片船响。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出见间,到底是詐尸還是另有隱情聊闯,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布米诉,位于F島的核電站菱蔬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏史侣。R本人自食惡果不足惜拴泌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望惊橱。 院中可真熱鬧蚪腐,春花似錦、人聲如沸税朴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掉房。三九已至茧跋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卓囚,已是汗流浹背瘾杭。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哪亿,地道東北人粥烁。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蝇棉,于是被迫代替她去往敵國和親讨阻。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容