前端最全知識(shí)點(diǎn)匯總(面試必備)

一年前寫(xiě)了一篇JavaScript八張思維導(dǎo)圖凭豪,主要是對(duì)前端JavaScript知識(shí)點(diǎn)的一個(gè)系統(tǒng)的整理和總結(jié)镐确。本篇文章用了近一個(gè)月時(shí)間寓盗,搜集整理了網(wǎng)上各種面試筆試題及本人針對(duì)前端的一些理解以及各路大神針對(duì)前端難點(diǎn)部分的詳細(xì)介紹南吮,可以作為以后面試或者考察面試人員的參考蜜猾。
相信通過(guò)這兩篇文章的學(xué)習(xí),一定會(huì)讓你對(duì)前端有一個(gè)更深的認(rèn)識(shí)柿菩。

如果覺(jué)得對(duì)你有所幫助戚嗅,希望能夠動(dòng)動(dòng)手指給個(gè)Star(O(∩_∩)O)。

后續(xù)會(huì)持續(xù)更新......

JavaScript基礎(chǔ)

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

string number boolean undefined null

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

  • 數(shù)據(jù)封裝類對(duì)象: String Number Boolean Array Object
  • 其他對(duì)象: Function Math Date Error Arguments RegExp

宿主對(duì)象和原生對(duì)象的區(qū)別

  • 原生對(duì)象(native object)是由ECMAScript規(guī)范定義的JavaScript內(nèi)置對(duì)象,如 String Number Boolean Array Object Function Math Date Error Arguments RegExp等碳褒。
  • 宿主對(duì)象(host object)是由運(yùn)行時(shí)的環(huán)境(瀏覽器或node)決定的折砸,如window、XMLHTTPRequest等沙峻。

null睦授、undefined及未聲明變量之間的區(qū)別。如何區(qū)分摔寨?

  • 未聲明變量默認(rèn)值為undefined
  • typeof null === 'object' // true
  • typeof undefined === 'undefined' // true

==和===的區(qū)別

  • ==比較之前會(huì)先進(jìn)行類型轉(zhuǎn)換去枷,即不會(huì)對(duì)類型進(jìn)行比較。例如:

      12 == '12'  // true
      true == 1   // true
      false == '0' // true
    
  • ===會(huì)比較數(shù)值和類型祷肯。例如:

      12 == '12' // false
      12 == 12 // true
      true == 1 // false
      false == '0' // false
    

JS隱式轉(zhuǎn)換及應(yīng)用場(chǎng)景

JS在使用運(yùn)算符號(hào)或者對(duì)比符時(shí)沉填,會(huì)自帶隱式轉(zhuǎn)換,規(guī)則如下:

  • -佑笋、*翼闹、/、% :一律轉(zhuǎn)換成數(shù)值后計(jì)算

  • +:

    • 數(shù)字 + 字符串 = 字符串蒋纬, 運(yùn)算順序是從左到右
    • 數(shù)字 + 對(duì)象猎荠, 優(yōu)先調(diào)用對(duì)象的valueOf -> toString
    • 數(shù)字 + boolean/null -> 數(shù)字
    • 數(shù)字 + undefined -> NaN
  • [1].toString() === '1'

  • {}.toString() === '[object object]'

  • NaN !== NaN 、+undefined 為 NaN

  • https://juejin.im/post/5a7172d9f265da3e3245cbca

"Attribute"和"Property"的區(qū)別

"Attribute"是在HTML中定義的蜀备,而"property"是在DOM上定義的关摇。為了說(shuō)明區(qū)別,假設(shè)我們?cè)贖TML中有一個(gè)文本框:
<input type="text" value="Hello">

const input = document.querySelector('input');
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello

但是在文本框中鍵入“ World!”后:

console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!

NaN是什么碾阁?如何判斷是否是NaN類型

  • 定義: 全局屬性 NaN 的值表示不是一個(gè)數(shù)字(Not-A-Number)

  • 如何判斷一個(gè)值是否是NaN: 等號(hào)運(yùn)算符(== 和 ===) 不能被用來(lái)判斷一個(gè)值是否是 NaN输虱。必須使用 Number.isNaN() 或 isNaN() 函數(shù)。

      NaN === NaN;        // false
      Number.NaN === NaN; // false
      isNaN(NaN);         // true
      isNaN(Number.NaN);  // true
    

如何判斷兩個(gè)對(duì)象相等

需要考慮三個(gè)問(wèn)題:

  1. 如果對(duì)象的屬性值之一本身就是一個(gè)對(duì)象
  2. 如果屬性值中的一個(gè)是NaN(在JavaScript中脂凶,是不是等于自己唯一的價(jià)值宪睹?)
  3. 如果一個(gè)屬性的值為undefined愁茁,而另一個(gè)對(duì)象沒(méi)有這個(gè)屬性(因而計(jì)算結(jié)果為不確定?)

檢查對(duì)象的“值相等”的一個(gè)強(qiáng)大的方法亭病,最好是依靠完善的測(cè)試庫(kù)鹅很,涵蓋了各種邊界情況。Underscore和Lo-Dash有一個(gè)名為_(kāi).isEqual()方法罪帖,用來(lái)比較好的處理深度對(duì)象的比較促煮。您可以使用它們像這樣:

// Outputs: true
console.log(_.isEqual(obj1, obj2));

什么是'user strict',使用它有什么優(yōu)缺點(diǎn)整袁?

'use strict' 是用于對(duì)整個(gè)腳本或單個(gè)函數(shù)啟用嚴(yán)格模式的語(yǔ)句菠齿。嚴(yán)格模式是可選擇的一個(gè)限制 JavaScript 的變體一種方式 。
優(yōu)點(diǎn):

  • 無(wú)法再意外創(chuàng)建全局變量坐昙。
  • 會(huì)使引起靜默失斉⒌薄(silently fail,即:不報(bào)錯(cuò)也沒(méi)有任何效果)的賦值操拋出異常民珍。
  • 試圖刪除不可刪除的屬性時(shí)會(huì)拋出異常(之前這種操作不會(huì)產(chǎn)生任何效果)襟士。
  • 要求函數(shù)的參數(shù)名唯一。
  • 全局作用域下嚷量,this的值為undefined陋桂。
  • 捕獲了一些常見(jiàn)的編碼錯(cuò)誤,并拋出異常蝶溶。
  • 禁用令人困惑或欠佳的功能嗜历。

缺點(diǎn):

  • 缺失許多開(kāi)發(fā)人員已經(jīng)習(xí)慣的功能。
  • 無(wú)法訪問(wèn)function.caller和function.arguments抖所。
  • 以不同嚴(yán)格模式編寫(xiě)的腳本合并后可能導(dǎo)致問(wèn)題梨州。

總的來(lái)說(shuō),我認(rèn)為利大于弊田轧,我從來(lái)不使用嚴(yán)格模式禁用的功能暴匠,因此我推薦使用嚴(yán)格模式。

call,apply和bind的作用是什么傻粘??jī)烧邊^(qū)別是什么每窖?

.call和.apply都用于調(diào)用函數(shù),第一個(gè)參數(shù)將用作函數(shù)內(nèi) this 的值弦悉。然而窒典,.call接受逗號(hào)分隔的參數(shù)作為后面的參數(shù),而.apply接受一個(gè)參數(shù)數(shù)組作為后面的參數(shù)稽莉。一個(gè)簡(jiǎn)單的記憶方法是瀑志,從call中的 C 聯(lián)想到逗號(hào)分隔(comma-separated),從apply中的 A 聯(lián)想到數(shù)組(array)。

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

console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3

.call和.apply是立即執(zhí)行的, .bind 返回函數(shù)的副本劈猪,但帶有綁定上下文缩膝!它不是立即執(zhí)行的。

const person = { name: 'Lydia' }

function sayHi(age) {
console.log(`${this.name} is ${age}`)
}

sayHi.call(person, 21)
sayHi.bind(person, 21)

結(jié)果: Lydia is 21 function

請(qǐng)說(shuō)明Function.prototype.bind的用法

摘自MDN:

bind()方法創(chuàng)建一個(gè)新的函數(shù), 當(dāng)被調(diào)用時(shí)岸霹,將其 this 關(guān)鍵字設(shè)置為提供的值,在調(diào)用新函數(shù)時(shí)将饺,在任何提供之前提供一個(gè)給定的參數(shù)序列贡避。

根據(jù)我的經(jīng)驗(yàn),將this的值綁定到想要傳遞給其他函數(shù)的類的方法中是非常有用的予弧。在 React 組件中經(jīng)常這樣做刮吧。

如何判斷是否為空數(shù)組

var arr = [];
if (Array.isArray(arr) && arr.length === 0) {
    console.log('是空數(shù)組');
}
// Array.isArray是ES5提供的,如果不支持掖蛤。用下面的方案杀捻。
if (!Array.isArray) {
    Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
    };
}

數(shù)組方法

  • map: 遍歷數(shù)組,返回回調(diào)返回值組成的新數(shù)組
  • forEach: 無(wú)法break蚓庭,可以用try/catch中throw new Error來(lái)停止
  • filter: 過(guò)濾
  • some: 有一項(xiàng)返回true致讥,則整體為true
  • every: 有一項(xiàng)返回false,則整體為false
  • join: 通過(guò)指定連接符生成字符串
  • sort(fn) / reverse: 排序與反轉(zhuǎn)器赞,改變?cè)瓟?shù)組
  • concat: 連接數(shù)組垢袱,不影響原數(shù)組, 淺拷貝
  • slice(start, end): 返回截?cái)嗪蟮男聰?shù)組港柜,不改變?cè)瓟?shù)組
  • splice(start, number, value...): 返回刪除元素組成的數(shù)組请契,value 為插入項(xiàng),改變?cè)瓟?shù)組
  • indexOf / lastIndexOf(value, fromIndex): 查找數(shù)組項(xiàng)夏醉,返回對(duì)應(yīng)的下標(biāo)
  • reduce / reduceRight(fn(prev, cur), defaultPrev): 兩兩執(zhí)行爽锥,prev 為上次化簡(jiǎn)函數(shù)的return值,cur 為當(dāng)前值(從第二項(xiàng)開(kāi)始)

數(shù)組亂序:

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.sort(function () {
    return Math.random() - 0.5;
});

數(shù)組拆解:

// flat: [1,[2,3]] --> [1, 2, 3]

Array.prototype.flat = function() {
    return this.toString().split(',').map(item => +item )
}

push畔柔、pop氯夷、shift、unshift功能及返回值

  • push:添加新元素到數(shù)組末尾靶擦,返回?cái)?shù)組長(zhǎng)度
  • pop:移除數(shù)組最后一個(gè)元素肠槽,返回元素本身
  • unshift:添加新元素到數(shù)組開(kāi)頭,返回?cái)?shù)組長(zhǎng)度
  • shift:移除數(shù)組首個(gè)元素奢啥,返回元素本身

以上4種操作均會(huì)改變數(shù)組本身

.forEach和.map()循環(huán)的主要區(qū)別秸仙,使用場(chǎng)景舉例

map用法:

let array = [1, 2, 3, 4, 5];
let newArray = array.map((item, i, arr) => {
    return item * 2;
});
console.log("array:", array);       // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // [2, 4, 6, 8, 10]
// 此處的array接受map方法運(yùn)算之后的返回值
// 但是map方法并不能改變?cè)瓉?lái)的數(shù)組

forEach用法:

let array = [1, 2, 3, 4, 5];
let newArray = array.forEach((item, i, arr) => {
    console.log('item:' + item + ', index:' + i);
    // array[i] = item * 2;    // 可以用這種方式改變?cè)紨?shù)組的值
});
console.log("array:", array);       // [1, 2, 3, 4, 5]
console.log("newArray:", newArray); // undefined
// forEach方法沒(méi)有返回值
  • 能用forEach()做到的,map()同樣可以桩盲。反過(guò)來(lái)也是如此寂纪。
  • map()會(huì)分配內(nèi)存空間存儲(chǔ)新數(shù)組并返回,forEach()不會(huì)返回?cái)?shù)據(jù)。
  • forEach()允許callback更改原始數(shù)組的元素捞蛋。map()返回新的數(shù)組孝冒。

JS執(zhí)行對(duì)象查找時(shí),永遠(yuǎn)不會(huì)去查找原型的函數(shù)是哪個(gè)拟杉?

Object?.prototype?.has?OwnProperty()

如何將arguments轉(zhuǎn)為數(shù)組

  1. Array.prototype.slice.call(arguments)
  2. [].slice.call(arguments)

對(duì)象的遍歷方法

  • for循環(huán)

      for (let property in obj) {
          console.log(property);
      }
    

    但是庄涡,這還會(huì)遍歷到它的繼承屬性,在使用之前搬设,你需要加入obj.hasOwnProperty(property)檢查穴店。

  • Object.keys()

      Object.keys(obj).forEach((property) => { ... })
    

    Object.keys()方法會(huì)返回一個(gè)由一個(gè)給定對(duì)象的自身可枚舉屬性組成的數(shù)組。

  • Object.getOwnPropertyNames()

      Object.getOwnPropertyNames(obj).forEach((property) => { ... })
    

    Object.getOwnPropertyNames()方法返回一個(gè)由指定對(duì)象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括 Symbol 值作為名稱的屬性)組成的數(shù)組拿穴。

數(shù)組的遍歷方法

  • for loops

      for (let i = 0; i < arr.length; i++) { ... }
    
  • forEach

      arr.forEach((item, index, arr) { ... })
    
  • map

      arr.map((item, index, arr) => { ... })
    

匿名函數(shù)的典型應(yīng)用場(chǎng)景

匿名函數(shù)可以在 IIFE 中使用泣洞,來(lái)封裝局部作用域內(nèi)的代碼,以便其聲明的變量不會(huì)暴露到全局作用域默色。

(function() {
    // 一些代碼球凰。
})();

匿名函數(shù)可以作為只用一次,不需要在其他地方使用的回調(diào)函數(shù)腿宰。當(dāng)處理函數(shù)在調(diào)用它們的程序內(nèi)部被定義時(shí)呕诉,代碼具有更好地自閉性和可讀性,可以省去尋找該處理函數(shù)的函數(shù)體位置的麻煩吃度。

setTimeout(function() {
    console.log('Hello world!');
}, 1000);

匿名函數(shù)可以用于函數(shù)式編程或 Lodash(類似于回調(diào)函數(shù))义钉。

const arr = [1, 2, 3];
const double = arr.map(function(el) {
    return el * 2;
});
console.log(double); // [2, 4, 6]

IIFE(立即執(zhí)行函數(shù))的用法

IIFE( 立即調(diào)用函數(shù)表達(dá)式)是一個(gè)在定義時(shí)就會(huì)立即執(zhí)行的 JavaScript 函數(shù)。

(function () {
    statements
})();

這是一個(gè)被稱為 自執(zhí)行匿名函數(shù) 的設(shè)計(jì)模式规肴,主要包含兩部分捶闸。第一部分是包圍在 圓括號(hào)運(yùn)算符 () 里的一個(gè)匿名函數(shù),這個(gè)匿名函數(shù)擁有獨(dú)立的詞法作用域拖刃。這不僅避免了外界訪問(wèn)此 IIFE 中的變量删壮,而且又不會(huì)污染全局作用域。

第二部分再一次使用 () 創(chuàng)建了一個(gè)立即執(zhí)行函數(shù)表達(dá)式兑牡,JavaScript 引擎到此將直接執(zhí)行函數(shù)央碟。

document的load事件和DOMContentLoaded事件之間的區(qū)別

當(dāng)初始的 HTML 文檔被完全加載和解析完成之后,DOMContentLoaded事件被觸發(fā)均函,而無(wú)需等待樣式表亿虽、圖像和子框架的完成加載。

window的load事件僅在 DOM 和所有相關(guān)資源全部完成加載后才會(huì)觸發(fā)苞也。

數(shù)據(jù)類型判斷方式有幾種

下面將對(duì)如下數(shù)據(jù)進(jìn)行判斷它們的類型

var bool = true
var num = 1
var str = 'abc'
var und = undefined
var nul = null
var arr = [1, 2, 3]
var obj = {a: 'aa', b: 'bb'}
var fun = function() {console.log('I am a function')}
  • typeof: 適合基本的數(shù)據(jù)類型和函數(shù)

      console.log(typeof bool);   // boolean
      console.log(typeof num);    // number
      console.log(typeof str);    // string
      console.log(typeof und);    // undefined
      console.log(typeof nul);    // object
      console.log(typeof arr);    // object
      console.log(typeof obj);    // object
      console.log(typeof fun);    // function
    

    由結(jié)果可知typeof可以測(cè)試出number洛勉、string、boolean如迟、undefined及function收毫,而對(duì)于null及數(shù)組攻走、對(duì)象,typeof均檢測(cè)出為object此再,不能進(jìn)一步判斷它們的類型昔搂。

  • instanceof: 判斷對(duì)象類型,基于原型鏈去判斷输拇。
    obj instanceof Object: 左操作數(shù)是一個(gè)對(duì)象摘符,右操作數(shù)是一個(gè)函數(shù)構(gòu)造器或者函數(shù)對(duì)象,判斷左邊的操作數(shù)的原型鏈proto屬性是否有右邊這個(gè)函數(shù)對(duì)象的proptotype屬性策吠。

      console.log(bool instanceof Boolean);// false
      console.log(num instanceof Number); // false
      console.log(str instanceof String); // false
      console.log(und instanceof Object); // false
      console.log(arr instanceof Array);  // true
      console.log(nul instanceof Object); // false
      console.log(obj instanceof Object); // true
      console.log(fun instanceof Function);// true
    
      var bool2 = new Boolean()
      console.log(bool2 instanceof Boolean);// true
    
      var num2 = new Number()
      console.log(num2 instanceof Number);// true
    
      var str2 = new String()
      console.log(str2 instanceof String);//  true
    
      function Animation(){}
      var ani = new Animation()
      console.log(ani instanceof Animation);// true
    
      function Dog(){}
      Dog.prototype = new Animation()
      var dog = new Dog()
      console.log(dog instanceof Dog);    // true
      console.log(dog instanceof Animation);// true
      console.log(dog instanceof Object); // true
    

    從結(jié)果中看出instanceof不能區(qū)別undefined和null逛裤,而且對(duì)于基本類型如果不是用new聲明的則也測(cè)試不出來(lái),對(duì)于是使用new聲明的類型奴曙,它還可以檢測(cè)出多層繼承關(guān)系。

  • constructor: 返回對(duì)創(chuàng)建此對(duì)象的函數(shù)的引用

      console.log(bool.constructor === Boolean);  // true
      console.log(num.constructor === Number);    // true
      console.log(str.constructor === String);    // true
      console.log(arr.constructor === Array);     // true
      console.log(obj.constructor === Object);    // true
      console.log(fun.constructor === Function);  // true
    
      console.log(ani.constructor === Animation); // true
      console.log(dog.constructor === Dog);       // false
      console.log(dog.constructor ===  Animation);// true
    

    null 和 undefined 是無(wú)效的對(duì)象草讶,因此是不會(huì)有 constructor 存在的洽糟,這兩種類型的數(shù)據(jù)需要通過(guò)其他方式來(lái)判斷。

    函數(shù)的 constructor 是不穩(wěn)定的堕战,這個(gè)主要體現(xiàn)在自定義對(duì)象上坤溃,當(dāng)開(kāi)發(fā)者重寫(xiě) prototype 后,原有的 constructor 引用會(huì)丟失嘱丢。所以dog.constructor === Animation 而不是 Dog

  • Object.prototype.toString.call

      console.log(Object.prototype.toString.call(bool));  //[object Boolean]
      console.log(Object.prototype.toString.call(num));   //[object Number]
      console.log(Object.prototype.toString.call(str));   //[object String]
      console.log(Object.prototype.toString.call(und));   //[object Undefined]
      console.log(Object.prototype.toString.call(nul));   //[object Null]
      console.log(Object.prototype.toString.call(arr));   //[object Array]
      console.log(Object.prototype.toString.call(obj));   //[object Object]
      console.log(Object.prototype.toString.call(fun));   //[object Function]
    
      console.log(Object.prototype.toString.call(dog));   //[object Object]  
    

    原理(摘自高級(jí)程序設(shè)計(jì)3):在任何值上調(diào)用 Object 原生的 toString() 方法薪介,都會(huì)返回一個(gè) [object NativeConstructorName] 格式的字符串。每個(gè)類在內(nèi)部都有一個(gè) [[Class]] 屬性越驻,這個(gè)屬性中就指定了上述字符串中的構(gòu)造函數(shù)名汁政。
    但是它不能檢測(cè)非原生構(gòu)造函數(shù)的構(gòu)造函數(shù)名。

  • 使用jquery中的$.type

      console.log($.type(bool));  //boolean
      console.log($.type(num));   //number
      console.log($.type(str));   //string
      console.log($.type(und));   //undefined
      console.log($.type(nul));   //null
      console.log($.type(arr));   //array
      console.log($.type(obj));   //object
      console.log($.type(fun));   //function
    
      console.log($.type(dog));   //object
    

    $.type()內(nèi)部原理就是用的Object.prototype.toString.call()

DOM操作(增刪改查)

  • 添加操作

      let element = document.createElement("div");   // 創(chuàng)建元素
      body.appendChild(element);  // 將一個(gè)節(jié)點(diǎn)添加到指定父節(jié)點(diǎn)的子節(jié)點(diǎn)列表末尾
    
  • 刪除操作

      var oldChild = node.removeChild(child); // 刪除子元素
      ChildNode.remove() // 刪除元素
    
  • 修改操作

      Node.innerText // 修改元素文本內(nèi)容
      Element.innerHTML // 設(shè)置或獲取描述元素后代的HTML語(yǔ)句
    
  • 查找操作

      Document.getElementById() // 返回對(duì)擁有指定 id 的第一個(gè)對(duì)象的引用
      Document.querySelector() // 返回文檔中匹配指定的CSS選擇器的第一元素
      Document.querySelectorAll() // 返回與指定的選擇器組匹配的文檔中的元素列表
    
  • https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model

異步加載JS 的方式有哪些

瀏覽器下載除JS外的資源時(shí)缀旁,會(huì)并行下載记劈,以提高性能。但下載JS腳本時(shí)并巍,會(huì)禁止并行下載(稱為腳本阻塞Scripts Block Downloads)目木。瀏覽器遇到JS時(shí),必須等JS下載懊渡,解析刽射,執(zhí)行完后,才能繼續(xù)并行下載下一個(gè)資源剃执。原因是JS可能會(huì)改變頁(yè)面或改變JS間的依賴關(guān)系誓禁,例如A.js中用document.write改變頁(yè)面,B.js依賴于A.js肾档。因此要嚴(yán)格保證順序现横,不能并行下載。

由于瀏覽器在遇到<body>標(biāo)簽前是不會(huì)渲染頁(yè)面的,為了避免白屏戒祠,通常的建議是將JS放到<body>標(biāo)簽底下骇两,可以有最佳的用戶體驗(yàn)穿肄。

按推薦度排序:

  1. 動(dòng)態(tài)創(chuàng)建<script>標(biāo)簽(Dynamic Script Element)

     var script = document.createElement('script');  // 創(chuàng)建script標(biāo)簽
     script.type = "text/javascript";
     script.src = "A.js";
     document.getElementsByTagName('head')[0].appendChild(script);   // 塞進(jìn)頁(yè)面
    

    先用document.createElement(‘script’)生成一個(gè)script標(biāo)簽饮醇,再設(shè)置它的src屬性,最后將其插入到<head>中冗澈。

    script標(biāo)簽被插入到頁(yè)面的DOM樹(shù)后馏颂,就會(huì)開(kāi)始下載src屬性指定的腳本示血。而且通過(guò)動(dòng)態(tài)腳本元素下載腳本是異步的,不會(huì)阻塞頁(yè)面的其他下載和處理過(guò)程救拉,因此script標(biāo)簽插入<head>中也沒(méi)問(wèn)題难审。

  2. Script async

     <script type="text/javascript" src="A.js" async></script>
    

    瀏覽器解析到HTML里的該行script標(biāo)簽,發(fā)現(xiàn)指定為async亿絮,會(huì)異步下載解析執(zhí)行腳本告喊。

    async 是HTML5里為script標(biāo)簽新增的屬性,對(duì)于低版本瀏覽器會(huì)存在兼容性問(wèn)題派昧。

    它會(huì)在下載完成后立刻執(zhí)行黔姜,而不是會(huì)等到DOM加載完成之后再執(zhí)行,所以還是有可能會(huì)造成阻塞蒂萎。

    這種方式只適用于引用外部js文件的<script>標(biāo)簽秆吵。

    添加async屬性的js文件不應(yīng)該使用document.write方法。

    對(duì)多個(gè)帶有async的js文件五慈,它不能保證按順序執(zhí)行纳寂,它是哪個(gè)js文件先下載完就先執(zhí)行哪個(gè)。

  3. Script defer

     <script type="text/javascript" src="A.js" defer></script>
    

    瀏覽器解析到HTML里的該行script標(biāo)簽泻拦,發(fā)現(xiàn)指定為defer烈疚,會(huì)暫緩下載解析執(zhí)行腳本。而是等到頁(yè)面加載完畢后聪轿,才加載腳本(更精確地說(shuō)爷肝,是在DOM樹(shù)構(gòu)建完成后,在window.onload觸發(fā)前陆错,加載defer的腳本)灯抛。

    defer也是只適用于外部js文件,也不能在js中使用document.write方法音瓷。

    可以保證多個(gè)js文件的執(zhí)行順序就是它們?cè)陧?yè)面中出現(xiàn)的順序对嚼。

document.write和innerHTML有何區(qū)別

  • document.write會(huì)重繪整個(gè)頁(yè)面,如果不指定元素的話绳慎,它會(huì)覆蓋掉整個(gè)頁(yè)面內(nèi)容纵竖。
  • innerHTML只會(huì)重繪頁(yè)面的一部分漠烧。

jQuery.extend和jQuery.fn.extend的區(qū)別

針對(duì)jQuery性能的優(yōu)化方法

如何判斷當(dāng)前腳本運(yùn)行在瀏覽器還是node環(huán)境中

通過(guò)判斷Global對(duì)象是否為window,如果不為window靡砌,則當(dāng)前腳本運(yùn)行在node.js環(huán)境中已脓。

this === window ? 'browser' : 'node';

Canvas和SVG的比較

Ajax的原理

JS事件委托、事件冒泡

event.jpg

IE和Firefox的事件機(jī)制有何區(qū)別通殃,如何阻止冒泡度液?

  • IE只支持事件冒泡,火狐同時(shí)支持事件捕獲事件冒泡兩種画舌。
  • 阻止事件冒泡的方式不同
    IE: e.cancelBubble = true
    W3C: e.stopPropagation()

JS內(nèi)存空間的管理

  • 基礎(chǔ)數(shù)據(jù)類型與棧內(nèi)存
    JS中的基礎(chǔ)數(shù)據(jù)類型堕担,這些值都有固定的大小,往往都保存在棧內(nèi)存中曲聂,由系統(tǒng)自動(dòng)分配存儲(chǔ)空間霹购。我們可以直接操作保存在棧內(nèi)存空間的值,因此基礎(chǔ)數(shù)據(jù)類型都是按值訪問(wèn)朋腋。

    數(shù)據(jù)在棧內(nèi)存中的存儲(chǔ)與使用方式類似于數(shù)據(jù)結(jié)構(gòu)中的堆棧數(shù)據(jù)結(jié)構(gòu)齐疙,遵循后進(jìn)先出的原則。

    基礎(chǔ)數(shù)據(jù)類型: Number String Null Undefined Boolean

  • 引用數(shù)據(jù)類型與堆內(nèi)存
    與其他語(yǔ)言不同乍丈,JS的引用數(shù)據(jù)類型剂碴,比如數(shù)組Array把将、對(duì)象Object轻专、函數(shù)Function,它們值的大小是不固定的察蹲。引用數(shù)據(jù)類型的值是保存在堆內(nèi)存中的對(duì)象请垛。JavaScript不允許直接訪問(wèn)堆內(nèi)存中的位置,因此我們不能直接操作對(duì)象的堆內(nèi)存空間洽议。

stack_heap.png
在操作對(duì)象時(shí)宗收,實(shí)際上是在操作對(duì)象的引用而不是實(shí)際的對(duì)象。因此亚兄,引用類型的值都是按引用訪問(wèn)的混稽。這里的引用,我們可以粗淺地理解為保存在棧內(nèi)存中的一個(gè)地址审胚,該地址與堆內(nèi)存的實(shí)際值相關(guān)聯(lián)匈勋。

總結(jié):

棧內(nèi)存 堆內(nèi)存
存儲(chǔ)基礎(chǔ)數(shù)據(jù)類型 存儲(chǔ)引用數(shù)據(jù)類型
按值訪問(wèn) 按引用訪問(wèn)
存儲(chǔ)的值大小固定 存儲(chǔ)的值大小不定,可動(dòng)態(tài)調(diào)整
由系統(tǒng)自動(dòng)分配內(nèi)存空間 由開(kāi)發(fā)人員通過(guò)代碼分配
主要用來(lái)執(zhí)行程序 主要用來(lái)存放對(duì)象
空間小膳叨,運(yùn)行效率高 空間大洽洁,但是運(yùn)行效率相對(duì)較低
先進(jìn)后出,后進(jìn)先出 無(wú)序存儲(chǔ)菲嘴,可根據(jù)引用直接獲取

JS執(zhí)行上下文

JS變量對(duì)象詳解

請(qǐng)解釋變量提升

JS作用域及作用域鏈/閉包(closure)饿自,常用場(chǎng)景舉例說(shuō)明

請(qǐng)簡(jiǎn)述JS中的this

JS函數(shù)與函數(shù)式編程

JS原型汰翠,原型鏈。實(shí)現(xiàn)繼承的方式

JS有哪幾種創(chuàng)建對(duì)象的方式

  1. 利用Object構(gòu)造函數(shù)方式創(chuàng)建
  2. 利用對(duì)象字面量方式創(chuàng)建
  3. 利用工廠模式創(chuàng)建
  4. 利用構(gòu)造函數(shù)模式創(chuàng)建
  5. 利用原型方式創(chuàng)建
  6. 利用構(gòu)造函數(shù)和原型的組合模式創(chuàng)建

請(qǐng)解釋事件循環(huán)昭雌,調(diào)用堆棧和任務(wù)隊(duì)列的區(qū)別

談?wù)剬?duì)Promise的理解

ES6知識(shí)點(diǎn)

  1. var let const
  2. =>箭頭函數(shù)
  3. 模版字符串
  4. 解析結(jié)構(gòu)
  5. 函數(shù)默認(rèn)參數(shù)
  6. ...展開(kāi)運(yùn)算符
  7. class
  8. Promise

防抖與節(jié)流

防抖與節(jié)流函數(shù)是一種最常用的 高頻觸發(fā)優(yōu)化方式复唤,能對(duì)性能有較大的幫助。

  • 防抖 (debounce): 將多次高頻操作優(yōu)化為只在最后一次執(zhí)行城豁,通常使用的場(chǎng)景是:用戶輸入苟穆,只需再輸入完成后做一次輸入校驗(yàn)即可。

  • 節(jié)流(throttle): 每隔一段時(shí)間后執(zhí)行一次唱星,也就是降低頻率雳旅,將高頻操作優(yōu)化成低頻操作,通常使用場(chǎng)景: 滾動(dòng)條事件 或者 resize 事件间聊,通常每隔 100~500 ms執(zhí)行一次即可攒盈。

      function throttle(method, context) {
          clearTimeout(method.tID);
          method.tID = setTimeout(function () {
              method.call(context);
          }, 1000);
      }
    

    用法:

      function showTime() {
          console.log("nowDate:" + new Date().toLocaleDateString());
      }
    
      setInterval(function () {
          throttle(showTime);
      }, 2000);
    

模塊化

模塊化開(kāi)發(fā)在現(xiàn)代開(kāi)發(fā)中已是必不可少的一部分,它大大提高了項(xiàng)目的可維護(hù)哎榴、可拓展和可協(xié)作性型豁。通常,我們 在瀏覽器中使用 ES6 的模塊化支持尚蝌,在 Node 中使用 commonjs 的模塊化支持迎变。

分類:

  • es6: import / export
  • commonjs: require / module.exports / exports
  • amd: require / defined

require與import的區(qū)別

  • require支持 動(dòng)態(tài)導(dǎo)入,import不支持飘言,正在提案 (babel 下可支持)
  • require是 同步 導(dǎo)入衣形,import屬于 異步 導(dǎo)入
  • require是 值拷貝,導(dǎo)出值變化不會(huì)影響導(dǎo)入值姿鸿;import指向 內(nèi)存地址谆吴,導(dǎo)入值會(huì)隨導(dǎo)出值而變化

oAuth實(shí)現(xiàn)方案

如何實(shí)現(xiàn)單點(diǎn)登錄(Single Sign On)

請(qǐng)解釋SPA(單頁(yè)應(yīng)用),優(yōu)缺點(diǎn)是什么苛预?如何使其對(duì)SEO友好

單頁(yè)Web應(yīng)用(single page web application句狼,SPA),就是只有一張Web頁(yè)面的應(yīng)用热某,是加載單個(gè)HTML 頁(yè)面并在用戶與應(yīng)用程序交互時(shí)動(dòng)態(tài)更新該頁(yè)面的Web應(yīng)用程序腻菇。

單頁(yè)應(yīng)用SPA 多頁(yè)應(yīng)用MPA
組成 一個(gè)外殼頁(yè)面和多個(gè)頁(yè)面片段組成 多個(gè)完整頁(yè)面構(gòu)成
資源共用(css,js) 共用,只需在外殼部分加載 不共用昔馋,每個(gè)頁(yè)面都需要加載
刷新方式 頁(yè)面局部刷新或更改 整頁(yè)刷新
url 模式 a.com/#/pageone
a.com/#/pagetwo
a.com/pageone.html
a.com/pagetwo.html
用戶體驗(yàn) 頁(yè)面片段間的切換快筹吐,用戶體驗(yàn)良好
由于要一次加載所有的資源(html/js),故首屏加載慢
頁(yè)面切換加載緩慢绒极,流暢度不夠骏令,用戶體驗(yàn)比較差
首屏加載很快
轉(zhuǎn)場(chǎng)動(dòng)畫(huà) 容易實(shí)現(xiàn) 無(wú)法實(shí)現(xiàn)
數(shù)據(jù)傳遞 容易 依賴 url傳參、或者cookie 垄提、localStorage等
搜索引擎優(yōu)化(SEO) 需要單獨(dú)方案榔袋、實(shí)現(xiàn)較為困難周拐、不利于SEO檢索。
Prerender預(yù)渲染優(yōu)化SEO
實(shí)現(xiàn)方法簡(jiǎn)易
試用范圍 高要求的體驗(yàn)度凰兑、追求界面流暢的應(yīng)用 適用于追求高度支持搜索引擎的應(yīng)用
開(kāi)發(fā)成本 較高妥粟,常需借助專業(yè)的框架 較低,但頁(yè)面重復(fù)代碼多
維護(hù)成本 相對(duì)容易 相對(duì)復(fù)雜

前端性能優(yōu)化方案

以下是移動(dòng)端的優(yōu)化方案吏够,大部分Web端也同樣適用


performance.png

正則表達(dá)式

設(shè)計(jì)模式舉例(實(shí)現(xiàn)勾给、應(yīng)用、優(yōu)缺點(diǎn))

前端常用框架對(duì)比

JS編碼規(guī)范

瀏覽器相關(guān)

瀏覽器架構(gòu)

  • 用戶界面
  • 主進(jìn)程
  • 內(nèi)核
    • 渲染引擎
    • JS 引擎
      • 執(zhí)行棧
    • 事件觸發(fā)線程
      • 消息隊(duì)列
        • 微任務(wù)
        • 宏任務(wù)
    • 網(wǎng)絡(luò)異步線程
    • 定時(shí)器線程

瀏覽器下事件循環(huán)(Event Loop)

事件循環(huán)是指: 執(zhí)行一個(gè)宏任務(wù)锅知,然后執(zhí)行清空微任務(wù)列表播急,循環(huán)再執(zhí)行宏任務(wù),再清微任務(wù)列表

  • 微任務(wù) microtask(jobs): promise / ajax / Object.observe(該方法已廢棄)
  • 宏任務(wù) macrotask(task): setTimout / setInterval / script / IO / UI Rendering

瀏覽器解析流程

webkit.png

從輸入 url 到展示的過(guò)程

  • DNS 解析
  • TCP 三次握手
  • 發(fā)送請(qǐng)求售睹,分析 url桩警,設(shè)置請(qǐng)求報(bào)文(頭,主體)
  • 服務(wù)器返回請(qǐng)求的文件 (html)
  • 瀏覽器渲染
    • HTML parser --> DOM Tree
      • 標(biāo)記化算法昌妹,進(jìn)行元素狀態(tài)的標(biāo)記
      • dom 樹(shù)構(gòu)建
    • CSS parser --> Style Tree
      • 解析 css 代碼捶枢,生成樣式樹(shù)
    • attachment --> Render Tree
      • 結(jié)合 dom樹(shù) 與 style樹(shù),生成渲染樹(shù)
    • layout: 布局
    • GPU painting: 像素繪制頁(yè)面

功能檢測(cè)飞崖、功能推斷烂叔、navigator.userAgent的區(qū)別

功能檢測(cè)(feature detection)

功能檢測(cè)包括確定瀏覽器是否支持某段代碼,以及是否運(yùn)行不同的代碼(取決于它是否執(zhí)行)固歪,以便瀏覽器始終能夠正常運(yùn)行代碼功能蒜鸡,而不會(huì)在某些瀏覽器中出現(xiàn)崩潰和錯(cuò)誤。例如:

if ('geolocation' in navigator) {
// 可以使用 navigator.geolocation
} else {
// 處理 navigator.geolocation 功能缺失
}

Modernizr是處理功能檢測(cè)的優(yōu)秀工具昼牛。

功能推斷(feature inference)

功能推斷與功能檢測(cè)一樣术瓮,會(huì)對(duì)功能可用性進(jìn)行檢查康聂,但是在判斷通過(guò)后贰健,還會(huì)使用其他功能,因?yàn)樗僭O(shè)其他功能也可用恬汁,例如:

if (document.getElementsByTagName) {
element = document.getElementById(id);
}

非常不推薦這種方式伶椿。功能檢測(cè)更能保證萬(wàn)無(wú)一失。

UA 字符串

這是一個(gè)瀏覽器報(bào)告的字符串氓侧,它允許網(wǎng)絡(luò)協(xié)議對(duì)等方(network protocol peers)識(shí)別請(qǐng)求用戶代理的應(yīng)用類型脊另、操作系統(tǒng)、應(yīng)用供應(yīng)商和應(yīng)用版本约巷。它可以通過(guò)navigator.userAgent訪問(wèn)偎痛。 然而,這個(gè)字符串很難解析并且很可能存在欺騙性独郎。例如踩麦,Chrome 會(huì)同時(shí)作為 Chrome 和 Safari 進(jìn)行報(bào)告枚赡。因此,要檢測(cè) Safari谓谦,除了檢查 Safari 字符串贫橙,還要檢查是否存在 Chrome 字符串。不要使用這種方式反粥。
考慮到歷史原因及現(xiàn)代瀏覽器中用戶代理字符串(userAgent)的使用方式卢肃,通過(guò)用戶代理字符串來(lái)檢測(cè)特定的瀏覽器并不是一件輕松的事情。所以使用用戶代理檢測(cè)是最后的選擇才顿。
用戶代理檢測(cè)一般適用以下的情形:

  • 不能直接準(zhǔn)確的使用功能檢測(cè)莫湘。
  • 同一款瀏覽器在不同平臺(tái)下具備不同的能力。這個(gè)時(shí)候可能就有必要確定瀏覽器位于哪個(gè)平臺(tái)郑气。
  • 為了跟蹤分析等目的需要知道特定的瀏覽器逊脯。

瀏覽器版本檢測(cè)方式

可以使用navigator.userAgent。

JS同源策略(same-origin policy)

同源策略限制了從同一個(gè)源加載的文檔或腳本如何與來(lái)自另一個(gè)源的資源進(jìn)行交互竣贪。這是一個(gè)用于隔離潛在惡意文件的重要安全機(jī)制军洼。

下表給出了相對(duì)http://store.company.com/dir/page.html同源檢測(cè)的示例:

URL 結(jié)果 原因
http://store.company.com/dir2/other.html 成功 只有路徑不同
http://store.company.com/dir/inner/another.html 成功 只有路徑不同
https://store.company.com/secure.html 失敗 不同協(xié)議 ( https和http )
http://store.company.com:81/dir/etc.html 失敗 不同端口 ( http:// 80是默認(rèn)的)
http://news.company.com/dir/other.html 失敗 不同域名 ( news和store )

跨標(biāo)簽頁(yè)通訊

不同標(biāo)簽頁(yè)間的通訊,本質(zhì)原理就是去運(yùn)用一些可以 共享的中間介質(zhì)演怎,因此比較常用的有以下方法:

  • 通過(guò)父頁(yè)面window.open()和子頁(yè)面postMessage
    • 異步下匕争,通過(guò) window.open('about: blank') 和 tab.location.href = '*'
  • 設(shè)置同域下共享的localStorage與監(jiān)聽(tīng)window.onstorage
    • 重復(fù)寫(xiě)入相同的值無(wú)法觸發(fā)
    • 會(huì)受到瀏覽器隱身模式等的限制
  • 設(shè)置共享cookie與不斷輪詢臟檢查(setInterval)
  • 借助服務(wù)端或者中間層實(shí)現(xiàn)

跨域的解決方案

按實(shí)際使用量排序(個(gè)人理解):

瀏覽器數(shù)據(jù)本地存儲(chǔ)方法(localStroage、sessionStroage爷耀、cookie甘桑、indexedDB)

目前常見(jiàn)的存儲(chǔ)方式為以下三種:

  • Cookie
  • web存儲(chǔ) (locaStorage和seesionStorage)
  • IndexedDB
browser_storage.png

在H5出現(xiàn)之前,數(shù)據(jù)都是存儲(chǔ)在cookie中的歹叮。為了解決cookie的局限性引入了Web存儲(chǔ)跑杭,indexedDB用于客戶端存儲(chǔ)大量結(jié)構(gòu)化數(shù)據(jù)(包括, 文件/ blobs)。

共同點(diǎn):都是保存在瀏覽器端咆耿、且同源的
區(qū)別

Cookie localStorage sessionStorage indexedDB
容量大小 4kb左右 5M左右 5M左右 無(wú)限容量
過(guò)期時(shí)間 只在設(shè)置的過(guò)期時(shí)間之前一直有效德谅,
即使窗口或者瀏覽器關(guān)閉
始終有效 當(dāng)前瀏覽器窗口關(guān)閉前有效 始終有效
存儲(chǔ)方式 瀏覽器和服務(wù)器間來(lái)回傳遞 本地保存 本地保存 本地保存
作用域 在同源窗口中共享 在同源窗口中共享 在同源窗口并且同一窗口中共享 在同源窗口中共享

Web安全舉例

  • XSS(跨站腳本攻擊)幾種形式,防范手段萨螺,過(guò)濾哪些字符

  • csrf(跨站請(qǐng)求偽造)原理窄做,實(shí)現(xiàn),防范手段

  • sql注入

  • 命令行注入

  • DDoS(Distributed Denial of Service) 又叫分布式拒絕服務(wù)

  • 流量劫持
    DNS劫持
    HTTP劫持

  • 服務(wù)器漏洞

  • https://juejin.im/entry/5a559dd36fb9a01c9e45d896

狀態(tài)碼

Web Worker

現(xiàn)代瀏覽器為JavaScript創(chuàng)造的 多線程環(huán)境慰技⊥终担可以新建并將部分任務(wù)分配到worker線程并行運(yùn)行,兩個(gè)線程可 獨(dú)立運(yùn)行吻商,互不干擾掏颊,可通過(guò)自帶的 消息機(jī)制 相互通信。

限制:

  • 同源限制
  • 無(wú)法使用 document / window / alert / confirm
  • 無(wú)法加載本地資源

內(nèi)存泄露

  • 意外的全局變量: 無(wú)法被回收
  • 定時(shí)器: 未被正確關(guān)閉艾帐,導(dǎo)致所引用的外部變量無(wú)法被釋放
  • 事件監(jiān)聽(tīng): 沒(méi)有正確銷毀 (低版本瀏覽器可能出現(xiàn))
  • 閉包: 會(huì)導(dǎo)致父級(jí)中的變量無(wú)法被釋放
  • dom 引用: dom 元素被刪除時(shí)乌叶,內(nèi)存中的引用未被正確清空

可用 chrome 中的 timeline 進(jìn)行內(nèi)存標(biāo)記改化,可視化查看內(nèi)存的變化情況,找出異常點(diǎn)枉昏。

HTTP緩存機(jī)制

cookie和session的區(qū)別

常見(jiàn)兼容性問(wèn)題(移動(dòng)端/PC端)

polyfill的作用

代碼相關(guān)

44個(gè) Javascript 題解析

https://lidaguang1989.github.io/2018/01/javascript-puzzlers/

43個(gè) javascript 進(jìn)階問(wèn)題列表

https://github.com/lydiahallie/javascript-questions/blob/master/README-zh_CN.md

如何實(shí)現(xiàn)數(shù)組去重

正則實(shí)現(xiàn)trim()功能

function myTrim(str) {
let reg = /^\s+|\s+$/g;
return str.replace(reg, "");
}
console.log(myTrim('    asdf    '));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末陈肛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兄裂,更是在濱河造成了極大的恐慌句旱,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晰奖,死亡現(xiàn)場(chǎng)離奇詭異谈撒,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)匾南,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門啃匿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蛆楞,你說(shuō)我怎么就攤上這事溯乒。” “怎么了豹爹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵裆悄,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我臂聋,道長(zhǎng)光稼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任孩等,我火速辦了婚禮艾君,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肄方。我一直安慰自己冰垄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布扒秸。 她就那樣靜靜地躺著播演,像睡著了一般冀瓦。 火紅的嫁衣襯著肌膚如雪伴奥。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,549評(píng)論 1 312
  • 那天翼闽,我揣著相機(jī)與錄音拾徙,去河邊找鬼。 笑死感局,一個(gè)胖子當(dāng)著我的面吹牛尼啡,可吹牛的內(nèi)容都是我干的暂衡。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼崖瞭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼狂巢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起书聚,我...
    開(kāi)封第一講書(shū)人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唧领,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后雌续,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體斩个,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年驯杜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了受啥。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鸽心,死狀恐怖滚局,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顽频,我是刑警寧澤核畴,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站冲九,受9級(jí)特大地震影響谤草,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜莺奸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一丑孩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧灭贷,春花似錦温学、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至览妖,卻和暖如春轧拄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讽膏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工檩电, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓俐末,卻偏偏與公主長(zhǎng)得像料按,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子卓箫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361

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