2019-04-16 面試題:JS


title: JavaScript問題

JavaScript 的組成

JavaScript 由以下三部分組成:

  • ECMAScript(核心):JavaScript 語言基礎
  • 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ī)范蚯窥?

  • 代碼縮進,建議使用“四個空格”縮進
  • 代碼段使用花括號{}包裹
  • 語句結束使用分號;
  • 變量和函數(shù)在使用前進行聲明
  • 以大寫字母開頭命名構造函數(shù)塞帐,全大寫命名常量
  • 規(guī)范定義 JSON 對象拦赠,補全雙引號
  • 用{}和[]聲明對象和數(shù)組

如何編寫高性能的 JavaScript?

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

DOM 元素 e 的 e.getAttribute(propName)和 e.propName 有什么區(qū)別和聯(lián)系

  • e.getAttribute()榔幸,是標準 DOM 操作文檔元素屬性的方法颊咬,具有通用性可在任意文檔上使用,返回元素在源文件中設置的屬性
  • e.propName 通常是在 HTML 文檔中訪問特定元素的特性牡辽,瀏覽器解析元素后生成對應對象(如 a 標簽生成 HTMLAnchorElement),這些對象的特性會根據(jù)特定規(guī)則結合屬性設置得到敞临,對于沒有對應特性的屬性态辛,只能使用 getAttribute 進行訪問
  • e.getAttribute()返回值是源文件中設置的值,類型是字符串或者 null(有的實現(xiàn)返回"")
  • e.propName 返回值可能是字符串挺尿、布爾值奏黑、對象、undefined 等
  • 大部分 attribute 與 property 是一一對應關系编矾,修改其中一個會影響另一個熟史,如 id,title 等屬性
  • 一些布爾屬性<input hidden/>的檢測設置需要 hasAttribute 和 removeAttribute 來完成窄俏,或者設置對應 property
  • <a href="../index.html">link</a>中 href 屬性蹂匹,轉(zhuǎn)換成 property 的時候需要通過轉(zhuǎn)換得到完整 URL
  • 一些 attribute 和 property 不是一一對應如:form 控件中<input value="hello"/>對應的是 defaultValue,修改或設置 value property 修改的是控件當前值凹蜈,setAttribute 修改 value 屬性不會改變 value property

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

  • offsetWidth/offsetHeight 返回值包含 content + padding + border限寞,效果與 e.getBoundingClientRect()相同
  • clientWidth/clientHeight 返回值只包含 content + padding,如果有滾動條仰坦,也不包含滾動條
  • scrollWidth/scrollHeight 返回值包含 content + padding + 溢出內(nèi)容的尺寸

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

瀏覽器的渲染過程:

  • 解析 HTML 構建 DOM(DOM 樹)悄晃,并行請求 css/image/js
  • CSS 文件下載完成玫霎,開始構建 CSSOM(CSS 樹)
  • CSSOM 構建結束后,和 DOM 一起生成 Render Tree(渲染樹)
  • 布局(Layout):計算出每個節(jié)點在屏幕中的位置
  • 顯示(Painting):通過顯卡把頁面畫到屏幕上

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

  • DOM 樹與 HTML 標簽一一對應,包括 head 和隱藏元素
  • 渲染樹不包括 head 和隱藏元素庶近,大段文本的每一個行都是獨立節(jié)點翁脆,每一個節(jié)點都有對應的 css 屬性

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

  • 重繪:當渲染樹中的元素外觀(如:顏色)發(fā)生改變拦盹,不影響布局時鹃祖,產(chǎn)生重繪
  • 回流:當渲染樹中的元素的布局(如:尺寸、位置普舆、隱藏/狀態(tài)狀態(tài))發(fā)生改變時恬口,產(chǎn)生重繪回流
  • 注意:JS 獲取 Layout 屬性值(如:offsetLeft、scrollTop沼侣、getComputedStyle 等)也會引起回流祖能。因為瀏覽器需要通過回流計算最新值
  • 回流必將引起重繪,而重繪不一定會引起回流

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

  • 需要要對元素進行復雜的操作時养铸,可以先隱藏(display:"none"),操作完成后再顯示
  • 需要創(chuàng)建多個 DOM 節(jié)點時轧膘,使用 DocumentFragment 創(chuàng)建完后一次性的加入 document
  • 緩存 Layout 屬性值钞螟,如:var left = elem.offsetLeft; 這樣,多次使用 left 只產(chǎn)生一次回流
  • 盡量避免用 table 布局(table 元素一旦觸發(fā)回流就會導致 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)部屬性,這個屬性所對應的就是該對象的原型
  • JavaScript 的函數(shù)對象暇藏,除了原型 [proto] 之外蜜笤,還預置了 prototype 屬性
  • 當函數(shù)對象作為構造函數(shù)創(chuàng)建實例時,該 prototype 屬性值將被作為實例對象的原型 [proto]盐碱。

原型鏈:

  • 當一個對象調(diào)用的屬性/方法自身不存在時把兔,就會去自己 [proto] 關聯(lián)的前輩 prototype 對象上去找
  • 如果沒找到,就會去該 prototype 原型 [proto] 關聯(lián)的前輩 prototype 去找瓮顽。依次類推县好,直到找到屬性/方法或 undefined 為止。從而形成了所謂的“原型鏈”

原型特點:

  • JavaScript 對象是通過引用來傳遞的暖混,當修改原型時缕贡,與之相關的對象也會繼承這一改變

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

  • 原始數(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)一個類,怎么實例化這個類诀紊?

  1. 構造函數(shù)法(this + prototype) -- 用 new 關鍵字 生成實例對象
    • 缺點:用到了 this 和 prototype谒出,編寫復雜,可讀性差
  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();
  1. 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();
  };
 }
  1. 極簡主義法(消除 this 和 prototype) -- 調(diào)用 createNew() 得到實例對象
    • 優(yōu)點:容易理解惕澎,結構清晰優(yōu)雅莉测,符合傳統(tǒng)的"面向?qū)ο缶幊?的構造
 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();
  1. ES6 語法糖 class -- 用 new 關鍵字 生成實例對象
     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)繼承捣卤?

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

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

原型鏈繼承的缺點

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

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

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

組合式繼承

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

javascript 創(chuàng)建對象的幾種方式?

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

  1. 對象字面量的方式
person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  1. 用 function 來模擬無參的構造函數(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();
  1. 用 function 來模擬參構造函數(shù)來實現(xiàn)(用 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");//實例化毫炉、創(chuàng)建對象
maidou.eat();//調(diào)用eat方法
  1. 用工廠方式來創(chuàng)建(內(nèi)置對象)
var wcDog =new Object();
     wcDog.name="旺財";
     wcDog.age=3;
wcDog.work=function(){
    alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();
  1. 用原型方式來創(chuàng)建
function Dog(){

    }
Dog.prototype.name="旺財";
Dog.prototype.eat=function(){
    alert(this.name+"是個吃貨");
}
var wangcai =new Dog();
wangcai.eat();
  1. 用混合方式來創(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)部細節(jié)削罩,但局部函數(shù)可以查看其上層的函數(shù)細節(jié)碘箍,直至全局細節(jié)
  • 如果當前作用域沒有找到屬性或方法遵馆,會向上層作用域查找,直至全局函數(shù)丰榴,這種形式就是作用域鏈

談談 this 對象的理解

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

eval 是做什么的四濒?

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

  • 應該避免使用 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 文檔的標準啃沪,與編程語言及平臺無關
  • DOM0:提供了查詢和操作 Web 文檔的內(nèi)容 API。未形成標準茁裙,實現(xiàn)混亂。如:document.forms['login']
  • DOM1:W3C 提出標準化的 DOM,簡化了對文檔中任意部分的訪問和操作。如:JavaScript 中的 Document 對象
  • DOM2:原來 DOM 基礎上擴充了鼠標事件等細分模塊桩皿,增加了對 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í)行順序:判斷的關鍵是否目標元素

  • 非目標元素:根據(jù) W3C 的標準執(zhí)行:捕獲->目標元素->冒泡(不依據(jù)事件綁定順序)
  • 目標元素:依據(jù)事件綁定順序:先綁定的事件先執(zhí)行(不依據(jù)捕獲冒泡標準)
  • 最終順序:父元素捕獲->目標元素事件 1->目標元素事件 2->子元素捕獲->子元素冒泡->父元素冒泡
  • 注意:子元素事件執(zhí)行前提 事件確實“落”到子元素布局區(qū)域上,而不是簡單的具有嵌套關系

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

  • 該 DOM 上的事件如果被觸發(fā)赞厕,會執(zhí)行兩次(執(zhí)行次數(shù)等于綁定次數(shù))
  • 如果該 DOM 是目標元素艳狐,則按事件綁定順序執(zhí)行,不區(qū)分冒泡/捕獲
  • 如果該 DOM 是處于事件流中的非目標元素皿桑,則先執(zhí)行捕獲毫目,后執(zhí)行冒泡

事件的代理/委托

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

優(yōu)點:

  • 可以減少事件注冊诲侮,節(jié)省大量內(nèi)存占用
  • 可以將事件應用于動態(tài)添加的子元素上

缺點: 使用不當會造成事件在不應該觸發(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 只事件冒泡沟绪,不支持事件捕獲刮便;火狐同時支持件冒泡和事件捕獲。

阻止冒泡:

  • 取消默認操作: w3c 的方法是 e.preventDefault()绽慈,IE 則是使用 e.returnValue = false;
  • return false javascript 的 return false 只會阻止默認行為恨旱,而是用 jQuery 的話則既阻止默認行為又防止對象冒泡。
  • 阻止冒泡 w3c 的方法是 e.stopPropagation()久信,IE 則是使用 e.cancelBubble = true
[js] view plaincopy
function stopHandler(event)

    window.event?window.event.cancelBubble=true:event.stopPropagation();

}

參考鏈接:淺談 javascript 事件取消和阻止冒泡-開源中國 2015

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é)流腿椎?介紹一下應用場景和原理桌硫?

  • 函數(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 一個新的定時器重復以上流程肿嘲。

函數(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)
  • 屏幕坐標:設備物理屏幕的水平坐標(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"],相應 parseInt 接收參數(shù)如下

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

所以旭贬,parseInt 參數(shù) radix 不合法怔接,導致返回值為 NaN

new 操作符具體干了什么?

  • 創(chuàng)建實例對象稀轨,this 變量引用該對象扼脐,同時還繼承了構造函數(shù)的原型
  • 屬性和方法被加入到 this 引用的對象中
  • 新創(chuàng)建的對象由 this 所引用,并且最后隱式的返回 this

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

封裝選擇器瓦侮、調(diào)用第三方 API、設置和獲取樣式(自由回答)

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

  [].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 應到節(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 地址

什么是閉包(closure)雌澄,為什么要用它斋泄?

閉包是指有權訪問另一個函數(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');
   }

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

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

defer 和 async

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

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

ajax 的全稱:Asynchronous Javascript And XML

異步傳輸+js+xml

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

  • 創(chuàng)建 XMLHttpRequest 對象,也就是創(chuàng)建一個異步調(diào)用對象
  • 建一個新的 HTTP 請求,并指定該 HTTP 請求的方法郑现、URL 及驗證信息
  • 設置響應 HTTP 請求狀態(tài)變化的函數(shù)
  • 發(fā)送 HTTP 請求
  • 獲取異步調(diào)用返回的數(shù)據(jù)
  • 用 JavaScript 和 DOM 實現(xiàn)局部刷新

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

  • 同步:瀏覽器訪問服務器請求,用戶看得到頁面刷新荧降,重新發(fā)請求,等請求完接箫,頁面刷新,新內(nèi)容出現(xiàn)朵诫,用戶看到新內(nèi)容,進行下一步操作
  • 異步:瀏覽器訪問服務器請求辛友,用戶正常操作,瀏覽器后端進行請求剪返。等請求完废累,頁面不刷新,新內(nèi)容也會出現(xiàn)脱盲,用戶看到新內(nèi)容

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

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

DOM 操作——怎樣添加邑滨、移除、移動钱反、復制掖看、創(chuàng)建和查找節(jié)點?

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

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

添加、移除面哥、替換乙各、插入

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

查找

  • 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)雅降級

  • 漸進增強 :針對低版本瀏覽器進行構建頁面,保證最基本的功能,然后再針對高級瀏覽器進行效果乞旦、交互等改進和追加功能達到更好的用戶體驗贼穆。
  • 優(yōu)雅降級 :一開始就構建完整的功能,然后再針對低版本瀏覽器進行兼容

Javascript 垃圾回收方法

標記清除(mark and sweep)

  • 這是 JavaScript 最常見的垃圾回收方式兰粉,當變量進入執(zhí)行環(huán)境的時候故痊,比如函數(shù)中聲明一個變量,垃圾回收器將其標記為“進入環(huán)境”玖姑,當變量離開環(huán)境的時候(函數(shù)執(zhí)行結束)將其標記為“離開環(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)?0 的時 候备蚓,說明沒有變量在使用课蔬,這個值沒法被訪問了,因此可以將其占用的空間回收郊尝,這樣垃圾回收器會在運行的時候清理掉引用次數(shù)為 0 的值占用的空間

參考鏈接 內(nèi)存管理-MDN

用過哪些設計模式二跋?

  1. 工廠模式:
  • 主要好處就是可以消除對象間的耦合,通過使用工程方法而不是 new 關鍵字流昏。將所有實例化的代碼集中在一個位置防止代碼重復
  • 工廠模式解決了重復實例化的問題 扎即,但還有一個問題,那就是識別問題,因為根本無法 搞清楚他們到底是哪個對象的實例
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');//第二個實例
  1. 構造函數(shù)模式
  • 使用構造函數(shù)的方法 况凉,即解決了重復實例化的問題 谚鄙,又解決了對象識別的問題,該模式與工廠模式的不同之處在于
  • 構造函數(shù)方法沒有顯示的創(chuàng)建對象 (new Object());
  • 直接將屬性和方法賦值給 this 對象;
  • 沒有 renturn 語句

說說你對閉包的理解

使用閉包主要是為了設計私有的方法和變量刁绒。閉包的優(yōu)點是可以避免全局變量的污染闷营,缺點是閉包會常駐內(nèi)存,會增大內(nèi)存使用量知市,使用不當很容易造成內(nèi)存泄露傻盟。在 js 中,函數(shù)即閉包嫂丙,只有函數(shù)才會產(chǎn)生作用域的概念

閉包有三個特性:

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

請解釋一下 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)進行值復制(郴季茫考)

function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一個對象椅寺!')
    }

    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [] : {}
    for (let key in obj) {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    }

    return cloneObj
}

注意:for...in 法不支持拷貝 func、date蒋失、reg 和 err

// 代理法
function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一個對象返帕!')
    }

    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [...obj] : { ...obj }
    Reflect.ownKeys(cloneObj).forEach(key => {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })

    return cloneObj
}

說說嚴格模式的限制

  • 嚴格模式主要有以下限制:
  • 變量必須聲明后再使用
  • 函數(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

將時間設為當前時間往前一點

var date = new Date();
date.setDate(date.getDate() - 1);//真正的刪除

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

expires 的設置

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

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

假設:一個英文字符占用一個字節(jié)算行,一個中文字符占用兩個字節(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"));

請解釋什么是事件代理

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

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

  • attribute 是 dom 元素在文檔中作為 html 標簽擁有的屬性;
  • property 就是 dom 元素在 js 中作為對象擁有的屬性胚股。
  • 對于 html 的標準屬性來說笼痛,attribute 和 property 是同步的,是會自動更新的
  • 但是對于自定義的屬性來說琅拌,他們是不同步的

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

  • 后端響應頭設置 charset
  • 前端頁面<meta>設置 charset

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

按照 HTML 標準刻坊,在</body>結束后出現(xiàn)<script>或任何元素的開始標簽,都是解析錯誤
雖然不符合 HTML 標準党晋,但瀏覽器會自動容錯谭胚,使實際效果與寫在</body>之前沒有區(qū)別
瀏覽器的容錯機制會忽略<script>之前的</body>,視作<script>仍在 body 體內(nèi)未玻。省略</body></html>閉合標簽符合 HTML 標準灾而,服務器可以利用這一標準

<script> 放在 </head> 中會有什么問題?

在瀏覽器渲染頁面之前扳剿,它需要通過解析HTML標記然后構建DOM樹绰疤。在這個過程中,如果解析器遇到了一個腳本(script)舞终,它就會停下來轻庆,并且執(zhí)行這個腳本,然后才會繼續(xù)解析HTML敛劝。如果遇到了一個引用外部資源的腳本(script)余爆,它就必須停下來等待這個腳本資源的下載,而這個行為會導致一個或者多個的網(wǎng)絡往返夸盟,并且會延遲頁面的首次渲染時間蛾方。

還有一點是需要我們注意的,那就是外部引入的腳本(script)會阻塞瀏覽器的并行下載上陕,HTTP/1.1規(guī)范表明桩砰,瀏覽器在每個主機下并行下載的組件不超過兩個(也就是說,瀏覽器一次只能夠同時從同一個服務器加載兩個腳本)释簿;如果你網(wǎng)站的圖片是通過多個服務器提供的亚隅,那么按道理來說,你的網(wǎng)站可以一次并行下載多張圖片庶溶。但是煮纵,當我們網(wǎng)站在加載腳本的時候懂鸵;瀏覽器不會再啟動任何其它的下載,即使這些組件來自不同的服務器行疏。

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

  • 設置<script>屬性 async="async" (一旦腳本可用,則會異步執(zhí)行)
  • 動態(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);
  • 構造器調(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)();

簡單實現(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 階段的默認參數(shù):
  func.bind(that, arg1, arg2)();

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

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

  • 數(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
  • 對象:
    • object.hasOwnProperty(prop);
    • object.propertyIsEnumerable(prop);
    • object.valueOf();
    • object.toString();
    • object.toLocaleString();
    • Class.prototype.isPropertyOf(object);

Array.slice() 與 Array.splice() 的區(qū)別贞让?

  • slice -- “讀取”數(shù)組指定的元素龄减,不會對原數(shù)組進行修改

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

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

JavaScript 對象生命周期的理解征绎?

  • 當創(chuàng)建一個對象時蹲姐,JavaScript 會自動為該對象分配適當?shù)膬?nèi)存
  • 垃圾回收器定期掃描對象,并計算引用了該對象的其他對象的數(shù)量
  • 如果被引用數(shù)量為 0人柿,或惟一引用是循環(huán)的柴墩,那么該對象的內(nèi)存即可回收

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

  • JavaScript 內(nèi)存泄露指對象在不需要使用它時仍然存在凫岖,導致占用的內(nèi)存不能使用或回收
  • 未使用 var 聲明的全局變量
  • 閉包函數(shù)(Closures)
  • 循環(huán)引用(兩個對象相互引用)
  • 控制臺日志(console.log)
  • 移除存在綁定事件的 DOM 元素(IE)

在 javascript 中江咳,1 與 Number(1)有什么區(qū)別 [易混淆]

var a = Number(1) // 1
var b = new Number(1)  // Number {[[PrimitiveValue]]: 1}
typeof (a) // number
typeof (b) // object
a == b // true
  • var a = 1 是一個常量,而 Number(1)是一個函數(shù)
  • new Number(1)返回的是一個對象
  • a==b 為 true 是因為所以在求值過程中哥放,總是會強制轉(zhuǎn)為原始數(shù)據(jù)類型而非對象歼指,例如下面的代碼:
typeof 123 // "number"
typeof new Number(123) // "object"
123 instanceof Number // false
(new Number(123)) instanceof Number // true
123 === new Number(123) // false

參考地址:面試題:在 javascript 中,1 與 Number(1)有什么區(qū)別

console.log(!!(new Boolean(false))輸出什么 [易混淆]

true

布爾的包裝對象 Boolean 的對象實例甥雕,對象只有在 null 與 undefined 時踩身,才會認定為布爾的 false 值,布爾包裝對象本身是個對象社露,對象->布爾 都是 true挟阻,所以 new Boolean(false)其實是布爾的 true,看下面這段代碼:

if(new Boolean(false)){
    alert('true!!');
}

只有使用了 valueOf 后才是真正的轉(zhuǎn)換布爾值峭弟,與上面包裝對象與原始資料轉(zhuǎn)換說明的相同:

!!(new Boolean(false))  //true
(new Boolean(false)).valueOf() //false

為什么 JS 是單線程,而不是多線程 [掣礁耄考]

  • 單線程是指 JavaScript 在執(zhí)行的時候,有且只有一個主線程來處理所有的任務瞒瘸。
  • 目的是為了實現(xiàn)與瀏覽器交互坷备。
  • 我們設想一下,如果 JavaScript 是多線程的情臭,現(xiàn)在我們在瀏覽器中同時操作一個 DOM击你,一個線程要求瀏覽器在這個 DOM 中添加節(jié)點玉组,而另一個線程卻要求瀏覽器刪掉這個 DOM 節(jié)點,那這個時候瀏覽器就會很郁悶丁侄,他不知道應該以哪個線程為準惯雳。所以為了避免此類現(xiàn)象的發(fā)生,降低復雜度鸿摇,JavaScript 選擇只用一個主線程來執(zhí)行代碼石景,以此來保證程序執(zhí)行的一致性。

瀏覽器中的 Event Loop

[圖片上傳失敗...(image-508ce4-1555410311059)]

  • 主線程運行的時候會生成堆(heap)和棧(stack)拙吉;
  • js 從上到下解析方法潮孽,將其中的同步任務按照執(zhí)行順序排列到執(zhí)行棧中;
  • 當程序調(diào)用外部的 API 時筷黔,比如 ajax往史、setTimeout 等,會將此類異步任務掛起佛舱,繼續(xù)執(zhí)行執(zhí)行棧中的任務椎例,等異步任務返回結果后,再按照執(zhí)行順序排列到事件隊列中请祖;
  • 主線程先將執(zhí)行棧中的同步任務清空订歪,然后檢查事件隊列中是否有任務,如果有肆捕,就將第一個事件對應的回調(diào)推到執(zhí)行棧中執(zhí)行刷晋,若在執(zhí)行過程中遇到異步任務,則繼續(xù)將這個異步任務排列到事件隊列中慎陵。
  • 主線程每次將執(zhí)行棧清空后眼虱,就去事件隊列中檢查是否有任務,如果有席纽,就每次取出一個推到執(zhí)行棧中執(zhí)行捏悬,這個過程是循環(huán)往復的... ...,這個過程被稱為“Event Loop 事件循環(huán)”

參考地址:Event Loop 這個循環(huán)你曉得么胆筒?(附 GIF 詳解)-餓了么前端

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邮破,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子仆救,更是在濱河造成了極大的恐慌抒和,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤蔽,死亡現(xiàn)場離奇詭異摧莽,居然都是意外死亡,警方通過查閱死者的電腦和手機顿痪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門镊辕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來油够,“玉大人,你說我怎么就攤上這事征懈∈В” “怎么了?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵卖哎,是天一觀的道長鬼悠。 經(jīng)常有香客問我,道長亏娜,這世上最難降的妖魔是什么焕窝? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮维贺,結果婚禮上它掂,老公的妹妹穿的比我還像新娘。我一直安慰自己溯泣,他們只是感情好虐秋,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著发乔,像睡著了一般熟妓。 火紅的嫁衣襯著肌膚如雪雪猪。 梳的紋絲不亂的頭發(fā)上栏尚,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音只恨,去河邊找鬼译仗。 笑死,一個胖子當著我的面吹牛官觅,可吹牛的內(nèi)容都是我干的纵菌。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼休涤,長吁一口氣:“原來是場噩夢啊……” “哼咱圆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起功氨,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤序苏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后捷凄,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體忱详,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年跺涤,在試婚紗的時候發(fā)現(xiàn)自己被綠了匈睁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片监透。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖航唆,靈堂內(nèi)的尸體忽然破棺而出胀蛮,到底是詐尸還是另有隱情,我是刑警寧澤糯钙,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布醇滥,位于F島的核電站,受9級特大地震影響超营,放射性物質(zhì)發(fā)生泄漏鸳玩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一演闭、第九天 我趴在偏房一處隱蔽的房頂上張望不跟。 院中可真熱鬧,春花似錦米碰、人聲如沸窝革。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虐译。三九已至,卻和暖如春吴趴,著一層夾襖步出監(jiān)牢的瞬間漆诽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工锣枝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厢拭,地道東北人。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓撇叁,卻偏偏與公主長得像供鸠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子陨闹,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

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

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5楞捂? 答:HTML5是最新的HTML標準。 注意:講述HT...
    kismetajun閱讀 27,522評論 1 45
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,113評論 1 32
  • ??JavaScript 與 HTML 之間的交互是通過事件實現(xiàn)的。 ??事件觅廓,就是文檔或瀏覽器窗口中發(fā)生的一些特...
    霜天曉閱讀 3,503評論 1 11
  • 概要 64學時 3.5學分 章節(jié)安排 電子商務網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,223評論 0 3
  • 第3章 基本概念 3.1 語法 3.2 關鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,132評論 0 21