1. 程式人生 > >你還有這些JS問題需要掌握

你還有這些JS問題需要掌握

JavaScript 的組成

JavaScript 由以下三部分組成:

  • ECMAScript(核心):JavaScript 語言基礎

  • DOM(文件物件模型):規定了訪問 HTML 和 XML 的介面

  • BOM(瀏覽器物件模型):提供了瀏覽器視窗之間進行互動的物件和方法

JS 的基本資料型別和引用資料型別

  • 基本資料型別:undefined、null、boolean、number、string、symbol

  • 引用資料型別:object、array、function

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

  • 根據 navigator.userAgent // UA.toLowerCase().indexOf('chrome')

  • 根據 window 物件的成員 // 'ActiveXObject' in window

介紹 JS 有哪些內建物件?

  • 資料封裝類物件:Object、Array、Boolean、Number、String

  • 其他物件:Function、Arguments、Math、Date、RegExp、Error

  • ES6 新增物件:Symbol、Map、Set、Promises、Proxy、Reflect

說幾條寫 JavaScript 的基本規範?

  • 程式碼縮排,建議使用“四個空格”縮排

  • 程式碼段使用花括號{}包裹

  • 語句結束使用分號;

  • 變數和函式在使用前進行宣告

  • 以大寫字母開頭命名建構函式,全大寫命名常量

  • 規範定義 JSON 物件,補全雙引號

  • 用{}和[]宣告物件和陣列

如何編寫高效能的 JavaScript?

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

  • 將 js 指令碼放在頁面底部,加快渲染頁面

  • 將 js 指令碼將指令碼成組打包,減少請求

  • 使用非阻塞方式下載 js 指令碼

  • 儘量使用區域性變數來儲存全域性變數

  • 儘量減少使用閉包

  • 使用 window 物件屬性方法時,省略 window

  • 儘量減少物件成員巢狀

  • 快取 DOM 節點的訪問

  • 通過避免使用 eval() 和 Function() 構造器

  • 給 setTimeout() 和 setInterval() 傳遞函式而不是字串作為引數

  • 儘量使用直接量建立物件和陣列

  • 最小化重繪(repaint)和迴流(reflow)

DOM 元素 e 的 e.getAttribute(propName)和 e.propName 有什麼區別和聯絡

  • e.getAttribute(),是標準 DOM 操作文件元素屬性的方法,具有通用性可在任意文件上使用,返回元素在原始檔中設定的屬性

  • e.propName 通常是在 HTML 文件中訪問特定元素的特性,瀏覽器解析元素後生成對應物件(如 a 標籤生成 HTMLAnchorElement),這些物件的特性會根據特定規則結合屬性設定得到,對於沒有對應特性的屬性,只能使用 getAttribute 進行訪問

  • e.getAttribute()返回值是原始檔中設定的值,型別是字串或者 null(有的實現返回"")

  • e.propName 返回值可能是字串、布林值、物件、undefined 等

  • 大部分 attribute 與 property 是一一對應關係,修改其中一個會影響另一個,如 id,title 等屬性

  • 一些布林屬性<input hidden/>的檢測設定需要 hasAttribute 和 removeAttribute 來完成,或者設定對應 property

  • 像<a href="../index.html">link</a>中 href 屬性,轉換成 property 的時候需要通過轉換得到完整 URL

  • 一些 attribute 和 property 不是一一對應如:form 控制元件中<input value="hello"/>對應的是 defaultValue,修改或設定 value property 修改的是控制元件當前值,setAttribute 修改 value 屬性不會改變 value property

offsetWidth/offsetHeight,clientWidth/clientHeight 與 scrollWidth/scrollHeight 的區別

  • offsetWidth/offsetHeight 返回值包含 content + padding + border,效果與 e.getBoundingClientRect()相同

  • clientWidth/clientHeight 返回值只包含 content + padding,如果有滾動條,也不包含滾動條

  • scrollWidth/scrollHeight 返回值包含 content + padding + 溢位內容的尺寸

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

瀏覽器的渲染過程:

  • 解析 HTML 構建 DOM(DOM 樹),並行請求 css/image/js

  • CSS 檔案下載完成,開始構建 CSSOM(CSS 樹)

  • CSSOM 構建結束後,和 DOM 一起生成 Render Tree(渲染樹)

  • 佈局(Layout):計算出每個節點在螢幕中的位置

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

DOM 樹 和 渲染樹 的區別:

  • DOM 樹與 HTML 標籤一一對應,包括 head 和隱藏元素

  • 渲染樹不包括 head 和隱藏元素,大段文字的每一個行都是獨立節點,每一個節點都有對應的 css 屬性

重繪和迴流(重排)的區別和關係?

  • 重繪:當渲染樹中的元素外觀(如:顏色)發生改變,不影響佈局時,產生重繪

  • 迴流:當渲染樹中的元素的佈局(如:尺寸、位置、隱藏/狀態狀態)發生改變時,產生重繪迴流

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

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

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

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

  • 需要建立多個 DOM 節點時,使用 DocumentFragment 建立完後一次性的加入 document

  • 快取 Layout 屬性值,如:var left = elem.offsetLeft; 這樣,多次使用 left 只產生一次迴流

  • 儘量避免用 table 佈局(table 元素一旦觸發迴流就會導致 table 裡所有的其它元素迴流)

  • 避免使用 css 表示式(expression),因為每次呼叫都會重新計算值(包括載入頁面)

  • 儘量使用 css 屬性簡寫,如:用 border 代替 border-width, border-style, border-color 批量修改元素樣式:elem.className 和 elem.style.cssText 代替 elem.style.xxx

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

  • 在解析 HTML 生成 DOM 過程中,js 檔案的下載是並行的,不需要 DOM 處理到 script 節點。因此,script 的位置不影響首屏顯示的開始時間。

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

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

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

JavaScript 作用域:

  • 在 Java、C 等語言中,作用域為 for 語句、if 語句或{}內的一塊區域,稱為作用域;

  • 而在 JavaScript 中,作用域為 function(){}內的區域,稱為函式作用域。

JavaScript 變數宣告提升:

  • 在 JavaScript 中,函式宣告與變數宣告經常被 JavaScript 引擎隱式地提升到當前作用域的頂部。

  • 宣告語句中的賦值部分並不會被提升,只有名稱被提升

  • 函式宣告的優先順序高於變數,如果變數名跟函式名相同且未賦值,則函式宣告會覆蓋變數宣告

  • 如果函式有多個同名引數,那麼最後一個引數(即使沒有定義)會覆蓋前面的同名引數

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

原型:

  • JavaScript 的所有物件中都包含了一個 [proto] 內部屬性,這個屬性所對應的就是該物件的原型

  • JavaScript 的函式物件,除了原型 [proto] 之外,還預置了 prototype 屬性

  • 當函式物件作為建構函式建立例項時,該 prototype 屬性值將被作為例項物件的原型 [proto]。

原型鏈:

  • 當一個物件呼叫的屬性/方法自身不存在時,就會去自己 [proto] 關聯的前輩 prototype 物件上去找

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

原型特點:

  • JavaScript 物件是通過引用來傳遞的,當修改原型時,與之相關的物件也會繼承這一改變

JavaScript 有幾種型別的值?,你能畫一下他們的記憶體圖嗎

  • 原始資料型別(Undefined,Null,Boolean,Number、String)-- 棧

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

  • 兩種型別的區別是:儲存位置不同:

  • 原始資料型別是直接儲存在棧(stack)中的簡單資料段,佔據空間小、大小固定,屬於被頻繁使用資料;

  • 引用資料型別儲存在堆(heap)中的物件,佔據空間大、大小不固定,如果儲存在棧中,將會影響程式執行的效能;

  • 引用資料型別在棧中儲存了指標,該指標指向堆中該實體的起始地址。

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

JavaScript 如何實現一個類,怎麼例項化這個類?

  1. 建構函式法(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() 生成例項物件

    • 缺點:不能實現私有屬性和私有方法,例項物件之間也不能共享資料

 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) -- 呼叫 createNew() 得到例項物件

    • 優點:容易理解,結構清晰優雅,符合傳統的"面向物件程式設計"的構造

 var Cat = {
   age: 3, // 共享資料 -- 定義在類物件內,createNew() 外
   createNew: function () {
     var cat = {};
     // var cat = Animal.createNew(); // 繼承 Animal 類
     cat.name = "小咪";
     var sound = "喵喵喵"; // 私有屬性--定義在 createNew() 內,輸出物件外
     cat.makeSound = function () {
       alert(sound);  // 暴露私有屬性
     };
     cat.changeAge = function(num){
       Cat.age = num; // 修改共享資料
     };
     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 如何實現繼承?

  1. 建構函式繫結:使用 call 或 apply 方法,將父物件的建構函式繫結在子物件上

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); // 呼叫父類的constructor(x, y)
        this.color = color;
    }
    toString() {
        return this.color + ' ' + super.toString(); // 呼叫父類的toString()
    }
}

javascript 建立物件的幾種方式?

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

  1. 物件字面量的方式

person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  1. 用 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();
  1. 用 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方法
  1. 用工廠方式來建立(內建物件)

var wcDog =new Object();
     wcDog.name="旺財";
     wcDog.age=3;
wcDog.work=function(){
    alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();
  1. 用原型方式來建立

function Dog(){

    }
Dog.prototype.name="旺財";
Dog.prototype.eat=function(){
    alert(this.name+"是個吃貨");
}
var wangcai =new Dog();
wangcai.eat();
  1. 用混合方式來建立

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 是做什麼的?

eval 的功能是把對應的字串解析成 JS 程式碼並執行

  • 應該避免使用 eval,不安全,非常耗效能(先解析成 js 語句,再執行)

  • 由 JSON 字串轉換為 JSON 物件的時候可以用 eval('('+ str +')');

什麼是 Window 物件? 什麼是 Document 物件?

  • Window 物件表示當前瀏覽器的視窗,是 JavaScript 的頂級物件。

  • 我們建立的所有物件、函式、變數都是 Window 物件的成員。

  • Window 物件的方法和屬性是在全域性範圍內有效的。

  • Document 物件是 HTML 文件的根節點與所有其他節點(元素節點,文字節點,屬性節點, 註釋節點)

  • Document 物件使我們可以通過指令碼對 HTML 頁面中的所有元素進行訪問

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

介紹 DOM 的發展

  • DOM:文件物件模型(Document Object Model),定義了訪問 HTML 和 XML 文件的標準,與程式語言及平臺無關

  • DOM0:提供了查詢和操作 Web 文件的內容 API。未形成標準,實現混亂。如:document.forms['login']

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

  • DOM2:原來 DOM 基礎上擴充了滑鼠事件等細分模組,增加了對 CSS 的支援。如:getComputedStyle(elem, pseudo)

  • DOM3:增加了 XPath 模組和載入與儲存(Load and Save)模組。如:XPathEvaluator

介紹 DOM0,DOM2,DOM3 事件處理方式區別

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

事件的三個階段

捕獲、目標、冒泡

介紹事件“捕獲”和“冒泡”執行順序和事件的執行次數?

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

事件執行次數(DOM2-addEventListener):元素上繫結事件的個數

  • 注意 1:前提是事件被確實觸發

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

事件執行順序:判斷的關鍵是否目標元素

  • 非目標元素:根據 W3C 的標準執行:捕獲->目標元素->冒泡(不依據事件繫結順序)

  • 目標元素:依據事件繫結順序:先繫結的事件先執行(不依據捕獲冒泡標準)

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

  • 注意:子元素事件執行前提 事件確實“落”到子元素佈局區域上,而不是簡單的具有巢狀關係

在一個 DOM 上同時繫結兩個點選事件:一個用捕獲,一個用冒泡。事件會執行幾次,先執行冒泡還是捕獲?

  • 該 DOM 上的事件如果被觸發,會執行兩次(執行次數等於繫結次數)

  • 如果該 DOM 是目標元素,則按事件繫結順序執行,不區分冒泡/捕獲

  • 如果該 DOM 是處於事件流中的非目標元素,則先執行捕獲,後執行冒泡

事件的代理/委託

事件委託是指將事件繫結目標元素的到父元素上,利用冒泡機制觸發該事件

優點:

  • 可以減少事件註冊,節省大量記憶體佔用

  • 可以將事件應用於動態新增的子元素上

缺點: 使用不當會造成事件在不應該觸發時觸發

示例:

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

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

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 的事件處理有哪些區別?(必考)

繫結事件

  • 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 的區別?

  • target 只會出現在事件流的目標階段

  • currentTarget 可能出現在事件流的任何階段

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

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

如何派發事件(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);
    }
}

什麼是函式節流?介紹一下應用場景和原理?

  • 函式節流(throttle)是指阻止一個函式在很短時間間隔內連續呼叫。 只有當上一次函式執行後達到規定的時間間隔,才能進行下一次呼叫。 但要保證一個累計最小呼叫間隔(否則拖拽類的節流都將無連續效果)

  • 函式節流用於 onresize, onscroll 等短時間內會多次觸發的事件

  • 函式節流的原理:使用定時器做時間節流。 當觸發一個事件時,先用 setTimout 讓這個事件延遲一小段時間再執行。 如果在這個時間間隔內又觸發了事件,就 clearTimeout 原來的定時器, 再 setTimeout 一個新的定時器重複以上流程。

函式節流簡單實現:

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

區分什麼是“客戶區座標”、“頁面座標”、“螢幕座標”?

  • 客戶區座標:滑鼠指標在可視區中的水平座標(clientX)和垂直座標(clientY)

  • 頁面座標:滑鼠指標在頁面佈局中的水平座標(pageX)和垂直座標(pageY)

  • 螢幕座標:裝置物理螢幕的水平座標(screenX)和垂直座標(screenY)

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

  • elem.offsetLeft:返回元素相對於其定位父級左側的距離

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

  • elem.getBoundingClientRect():返回一個 DOMRect 物件,包含一組描述邊框的只讀屬性,單位畫素

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

答案:[1, NaN, NaN]

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

map 每次為 parseInt 傳 3 個引數(elem, index, array),其中 index 為陣列索引

因此,map 遍歷 ["1", "2", "3"],相應 parseInt 接收引數如下

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

所以,parseInt 引數 radix 不合法,導致返回值為 NaN

new 操作符具體幹了什麼?

  • 建立例項物件,this 變數引用該物件,同時還繼承了建構函式的原型

  • 屬性和方法被加入到 this 引用的物件中

  • 新建立的物件由 this 所引用,並且最後隱式的返回 this

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

封裝選擇器、呼叫第三方 API、設定和獲取樣式(自由回答)

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

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

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

  • $$(sel) // $$函式被許多現代瀏覽器命令列支援,等價於 document.querySelectorAll(sel)

  • [].forEach.call(NodeLists) // 使用 call 函式將陣列遍歷函式 forEach 應到節點元素列表

  • 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 之間的隨機浮點數

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

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

JavaScript 實現非同步程式設計的方法?

  • 回撥函式

  • 事件監聽

  • 釋出/訂閱

  • Promises 物件

  • Async 函式[ES7]

web 開發中會話跟蹤的方法有哪些

  • cookie

  • session

  • url 重寫

  • 隱藏 input

  • ip 地址

原文https://mp.weixin.qq.com/s/ijvf1_mKJEQcjMgeD5gFZQ