前端知識體系整理(不斷更新)

前端知識體系整理(不斷更新)

——人腦不是機器,記憶都會退化,我們需要文檔輔助作知識沉淀

javascript

基本功

語言特性
  • 數據類型:

    • Undefined,

      Null,

      Bollean,

      Number,

      String

    • ObjectArray

    • Date、RegExp

  • typeof輸出(以下六個值之一):

    • undefined
    var x;
    typeof(x); // "undefined"
    
    • boolean
    var x = false;
    typeof x; // "boolean"
    
    • string
    var x = '';
    typeof x; // "string"
    
    • number
    var x = NaN;
    typeof x; // "number"
    
    • object
    var x = {};
    var y = [];
    var z = null;
    typeof x; // "object"
    typeof y; // "object"
    typeof z; // "object"
    
    • function
    var x = function() {};
    typeof x; // "function"
    
類型轉換:
  • 簡單類型 -> 簡單類型:
'1'-0; // 0, equal to Number(1)
  • 簡單類型 -> 對象(使用基本函數的構造函數:Number(), String(), Boolean()等生成):
var n = 5;
console.log(n.toString(2)); // 快速進制轉換
  • 對象 -> 簡單類型(參考JavaScript 類型轉換

    1. 隱式轉換:除Date外,統統是先

      valueOf、再

      toStringDate

      +

      ==

      時優先轉化為字串):

    [] + 1; // 1
    
    1. 顯式Number(對象):先valueOf,再toString(),都不存在則返回NaN
    Number({}); // NaN
    
    1. 顯式String(對象):先取valueOf(),再取valueOf(),都不存在則拋異常:
    String({}); // [object Object]
    
DOM操作(增、刪、查、改、移、數據交換)
  • createElement,

    createTextNode,

    createDocumentFragment,

    appendChild

  • removeChild,

    removeNode

  • getElementById,

    getElementsByTagName,

    getElementsByClassName,

    querySelector,

    querySelectorAll,

    parentNode,

    firstChild,

    lastChild,

    nextSibling,

    previousSibling,

    childNodes

  • replaceChild,

    insertBefore

  • getAttribute,

    setAttribute,

    data-x,

    jQuery.attr(),

    jQuery().prop(),

    jQuery().data(),

    classList,

    innerHTML,

    innerText,

    textContent

事件機制(IE vs W3C)
  • 事件綁定與解綁:addEventListener(type, handler, flag),

    attechEvent('on' + type, handler),

    removeEventListener(type, handler),

    detechEvent('on' + type, handler)

  • 事件流:

    • 事件捕獲流:沿著文檔樹由外到內
    • 事件對象
    function handler(e) {
        var e = e || window.event;
        var target = e.target || e.srcElement;
        // e.currentTarget 指的是綁定事件的元素,不一定和target是同一個
    }
    
    • 事件冒泡流:沿著文檔樹由內到外,load、unload、focus、blur、submit和change事件不支持冒
OOP(原型鏈、繼承。。。)
  • 比較(參考

    全面理解面向對象的 JavaScript

    • 基于類Class的面向對象,對象由類Class產生:如JavaC#
    • javascript:基于原型prototype的OOP,對象由構造器(構造函數)constructor利用原型prototype產生
  • 生成js對象:

    1. 類JSON的對象字面量:簡單直觀,但不適用于復雜的對象(類)
    var Preson = {
        name: 'xiaoming',
        age: 15
    };
    
    1. 構造函數模式:存在內存浪費的問題,比如下面例子里的this.city,在內存里生成了多次
    var Person = function(name, age) {
        // 全部標記為私有成員
        this.name = name;
        this.age = age;
        this.city = 'shen zhen';
    };
    var xm = new Person('xiaoming', 15);
    var xl = new Person('xiaoli', 20);
    
    1. 原型prototype模式:每次實例化只增加私有的對象屬性(或方法)到實例中,所有實例的公有屬性(或方法)指向同一個內存地址
    var Person = function(name, age) {
        // 對象的私有成員
        this.name = name;
        this.age = age;
    };
    Person.prototype.city = 'shen zhen';// 共有成員
    
  • 對象的繼承

    1. 非構造函數的繼承:繼承可以簡單使用對象之間的深、淺拷貝

    2. 構造函數的繼承:大多是基于原型的繼承,但是閱讀性差,也不利于擴展

      1. 借調:依賴apply或者call實現
      function A(name) {
          this.name = name;
      }
      function B(name, age) {
          A.apply(this, arguments);
          this.age = age;
      }
      
      1. 子類prototype引用父類的prototype
      function A() {}
      A.prototype.propA = 'a';
      A.prototype.propB = 'b';
      function B() {}
      B.prototype = A.prototype; // 原型鏈引用,改成B.prototype = new A();可以解決引用的問題
      B.prototype.propB = 'B'; // 函數重載
      B.prototype.constructor = B;
      var b = new B();
      

      A、B的prototype引用同一個地址,實時上A的prototype.constructor已經被改成了B

      1. 借用空函數的prototype,類似YUI的實現:
      function extend(sub, sup) {
          var _f = function() {};
          _f.prototype = sup.prototype;
          sub.prototype = new _f();
          sub.prototype.constructor = sub;
          sub.super = sup.prototype;// 保存原構造函數
          _f = null;
      }
      A.prototype.propA = 'a';
      A.prototype.propB = 'b';
      function B() {}
      extend(B, A);
      

      構造函數的繼承,重要的是理解原型鏈prototype chain,繼承基本就是原型鏈的拷貝或者引用。

      理解原型鏈prototype chain

      function A() {}
      function B() {}
      B.prototype = new A();
      function C(x, y) {}
      C.prototype = new B();
      var c = new C();
      c.__proto__ === C.prototype;// true
      B.prototype.__proto__ === A.prototype;// true
      B.__proto__ === B.prototype;// true
      A.__proto__ === Function.prototype;// true
      A.prototype.__proto__ === Object.prototype;// true
      

      _proto屬性_:對象的__proto__指向Object.prototype,Function對象的__proto__指向構造函數的prototype。

    3. 類式繼承:本質上還是使用構造函數的prototype,封裝成類,典型的例子是jQuery之父John ResigSimple JavaScript Inheritance,其他類庫也有各自的實現

      • Simple Inheritance的用法
      var Person = Class.extend({
          init: function(gender) {
              this.gender = gender;
          }
      });
      var Teacher = Person.extend({
          init: funciton(gender, name) {
              this._super(gender);
              this.name = name;
          },
          role: 'teacher',
          speek: function() {
              console.log('Hello, i am a %s.', this.role);
          }
      });
      var Student = Person.extend({
          init: funciton(gender, name) {
              this._super(gender);
              this.name = name;
          },
          role: 'student',
          speek: function() {
              console.log('Hello, i am a %s.', this.role);
          }
      });
      
函數式編程、作用域、閉包、this
  • 實參、形參
foo(1, 2);
function foo(a, b, c) {
    console.log(arguments.length);//2 實際傳入的參數
    console.log(foo.length);//3 期望傳入的參數
}
  • 函數申明與函數表達式
function foo() {} // 函數申明
var foor = function foo() {};// 函數表達式

執行順序:解析器會率先讀取函數聲明,所以在任何代碼執行前函數申明可用

fn(2); // 4
function fn(n) {console.log(n);}
fn(2); // 4
function fn(n) {console.log(n*n);} //重載
fn(2); // 4
var fn = function(n) {console.log(++n);};// 函數表達式,按照申明的順序執行
fn(2); // 3
  • arguments, callee, caller, apply, call

    • arguments,類數組,類似的還有NodeList、classList等對象
    • arguments.callee,返回正在執行的Function對象的一個引用
    function foo(n) {
        console.log(arguments.callee.arguments.length);
        console.log(arguments.callee.length);
    }
    foo(1, 2, 3);// 分別打出3,1
    
    • arguments.caller,返回調用這個Function對象的Function對象的引用
    • applycall,傳參不同,功能相同,都是把Function對象綁定到另外一個對象上去執行,其內的this指向這個對象
  • 作用域

    • 函數的局部變量:函數形參、函數內部var聲明的變量
    • 變量的查找(作用域鏈):查找函數內部變量 -> 查找嵌套的外部函數 ...-> 查找window對象 -> 未定義
    • js中沒有塊級作用域,可以用匿名函數模擬
    • 未用關鍵字var申明的變量,會自動升級為全局變量掛到window上
    • 頂級作用域內使用var申明的變量是window對象的一個屬性
  • 閉包

    • 由于作用域的限制,函數外部不能訪問函數內部的局部變量
    • 閉包就是能夠讀取其他函數內部變量的函數引自學習Javascript閉包
    function foo() {
        var x = 1;
        return function fn() { // closure
            return x;
        }
    }
    var bar = foo();
    console.log(bar()); // get the local variables in foo
    
    • 閉包的另一個作用是在內存中保存函數的局部變量,這有可能導致內存泄露
  • this:函數中的this始終指向函數的調用者

function foo(x) {
    this.x = x;
}
foo(1); // 調用者是window,也可以window.foo()
console.log(window.x); // 1
var o = {};
o.foo = foo;
o.foo(2); // 調用者是o
console.log(o.x); // 2
console.log(window.x); // 1

這里有一篇詳細的例子

Ajax(XMLHttpRequest vs ActiveXObject)
  • 請求過程

    • 建立到服務器的新請求:xhr.open()
    • 向服務器發送請求:xhr.send()
    • 退出當前請求:xhr.abort()
    • 查詢當前HTML的就緒狀態:xhr.readyState
    • 服務器返回的請求響應文本:xhr.responseText
  • RUST API:POST,

    GET,

    PUT,

    DELETE

    • GET:更多的用于操作,參數暴露到url,(服務器端可能對)url長度有限制
    • POST:更多的用于操作
  • HTTP狀態碼

  • XHR2

跨域問題

  • 跨域的形成(同源限制):主域、子域、ip和域名、協議不同、端口不同
  • 常用解決方案
    • iframe+document.domain:適用于垮子域的情況
      缺點是如果一個域名下存在安全問題,另一個域名下可能也會有問題,還有就是創建iframe的開銷
    • 動態引入js腳本:適合所有的跨域場景
      引入的腳本會立刻執行,存在安全風險
      要與遠端溝通約定變量,增加了開發和維護成本
    • iframe+location.hash:適合各種場景下跨域
      iframe嵌套引用,開銷更大
      會產生歷史記錄,url中暴露傳遞的內容
    • iframe+window.name:使用iframe的window.name從外域傳遞數據到本地域,適合各種場景下跨域且數據安全
      缺點是數據有大小限制
    • postMessage跨域通訊

jQuery

可閱讀yuanyan同學的jQuery編程實踐

安全問題

  • XSS
  • CSRF
  • SQL注入
  • 敏感信息采用安全傳輸(SSL/HTTPS)
  • 上傳限制(大小、mime類型、可執行文件)
  • (服務器端)嚴格的路徑限制,比如杜絕路徑跳轉

css

  • css盒子模型
  • css的繼承規則
  • IE低版本的hacks
  • 瀏覽器的怪異模式與標準模式

性能優化(最佳實踐)

HTML優化

  • 語意化html結構:SEO友好,利于維護
  • 精簡html結構:嵌套過復雜的結構會導致瀏覽器構建DOM樹緩慢
  • html最小化:html大小直接關系到下載速度,移除內聯的css,javascript,甚至模板片,有條件的話盡可能壓縮html,去除注釋、空行等無用文本
  • 總是設置文檔字符集:如果不設置,瀏覽器在渲染頁面前會做一些查找,先搜索可進行解析的字符
  • 顯式設置圖片的寬高:減少頁面重繪(參考【高性能前端1】高性能HTML
  • 去除空鏈接屬性(img、link、script、iframe元素的srchref屬性被設置了,但是屬性卻為空):部分瀏覽器依然會去請求空地址
  • 正確的閉合標簽:瀏覽器不一定會將它們修復成正確的格式
  • 避免@import引入樣式表:IE低版本瀏覽器會再頁面構建好之后再去加載import的樣式表,會導致白屏
  • 樣式表放head里,腳本延后引入
  • 未完待續。。。

CSS優化

  • 避免css表達式:css表達式會不斷的重復計算,導致頁面性能下降

  • 避免AlphaImageLoader濾鏡:這個濾鏡的問題在于瀏覽器加載圖片時它會終止內容的呈現并且凍結瀏覽器(引自【高性能前端1】高性能CSS

  • 合并圖片(css sprites)

  • 盡量避免通配符選擇器:CSS選擇器是從右到左進行規則匹配,基于這個機制,瀏覽器會查找所有同類節點然后逐級往上查找,知道根節點,這樣效率很低

  • 盡量避免屬性選擇器(\*=,

    |=,

    ^=,

    $=,

    ~=):正則表達式匹配比基于類別的匹配慢

  • 移除無匹配的規則:縮減文檔體積;瀏覽器會把所有的樣式規則都解析后索引起來,即使是當前頁面無匹配的規則

  • 合并多條可合并的規則,使用簡寫:

.box {margin-top: 10px; margin-left: 5px; margin-bottom: 15px;} /* bad */
.box {margin: 10px 0 15px 5px;} /* better */
  • 對IE瀏覽器單獨使用hack:代碼清晰易讀,同時也減小樣式體積
  • 模塊化css,最好能夠組件化:查找、維護方便,同時也利于代碼復用
  • 完善注釋
  • 未完待列。。

JavaScript優化

  • 盡量減少或最少化對DOM的操作(脫離文檔流對DOM進行修改)

    • 隱藏元素,對其進行修改之后再顯示
    • 使用文檔片段DocumentFragement批量修改,最后再插入文檔
    • 將元素拷貝一份,修改完之后再替換原有元素
  • 謹慎操作節點集合NodeList(images,

    links,

    forms,

    document.getElementsByTagName):
    緩存NodeList以及NodeList.length的引用

  • 盡量操作元素節點(DOM節點如childNodes,

    firstChild不區分元素節點和其他類型節點,但大部分情況下只需要訪問元素節點引自《高性能JavaScript》):

    • children代替childNodes
    • childElementCount代替childNodes.length
    • firstElementChild代替firstChild
    • ...
  • 讀寫分離,減少layout:

x = box.offsetLeft; // read
box.offsetLeft = '100px'; // write
y = box.offsetTop; // read
box.offsetTop = '100px'; // write

這個過程造成了兩次的layout,可做如下改造:

x = box.offsetLeft; // read
y = box.offsetTop; // read
box.offsetLeft = '100px'; // write
box.offsetTop = '100px'; // write
  • 最小化重排(repeat):
box.style.width = '100px';
box.style.heihgt = '50px;';
box.style.left = '200px';

三個操作都會重新計算元素的幾何結構,在部分瀏覽器可能會導致3次重排,可做如下改寫:

var css = 'width: 100px; height: 50px; left: 200px;';
box.style.cssText += css;
  • 使用事件委托:充分利用冒泡機制,減少事件綁定
  • 無阻塞加載:腳本延后加載,合并加載,并行加載
  • 函數內部的變量盡可能使用局部變量,縮短變量作用域的查找時間
  • 緩存對象引用:
var a = $('#box .a');
var b = $('#box .b');

可以緩存$('#box')到臨時變量:

var box = $('#box');
var a = box.find('.a');
var b = box.find('.b');
  • 減少多級引用:
var $P = Jx().UI.Pager.create();// 同樣可以先緩存結果
  • 緩存Ajax:
    • 緩存Ajax數據,利用本地存儲或者臨時變量,存儲不需要實時更新的數據

    • 設置HTTP

      Expires信息

  • 復雜的計算考慮使用Web Worker

jQuery性能優化

合理使用選擇器
  • id和標簽選擇器最快,因為是直接調用原生API
$('#box'); // document.getElementById | document.querySelector
$('div'); // document.getElementsByTagName
  • 類選擇器在低版本瀏覽器較慢,偽元素、屬性選擇器在不支持querySelector的瀏覽器很慢
  • 盡可能優先使用符合CSS語法規范的CSS選擇器表達式,以此來避免使用jQuery自定義的選擇器表達式,因為當jQuery遇到單個id, 標簽名,類名,選擇器就會快速調用瀏覽器支持的DOM方法查詢
$('input[checked="checked"]'); // 比較快
$('input:checked'); // 較慢
  • 優先選擇$.fn.find查找子元素,因為find之前的選擇器并沒有使用 jQuery 自帶的 Sizzle 選擇器引擎,而是使用原生API查找元素
$('#parent').find('.child'); // 最快
$('.child', $('#parent')); // 較快,內部會轉換成第一條語句的形式,性能有一定損耗
$('#parent .child'); // 不如上一個語句塊
  • 使用組合選擇器時,盡可能讓右端更明確,因為Sizzle引擎是從右到左進行匹配的
$('div.foo .bar'); // slow
$('.foo div.bar'); // faster
  • 避免過度具體,簡潔的 DOM 結構也有助于提升選擇器的性能
$('.foo .bar .baz');
$('.foo div.baz'); // better
  • 盡量避免使用通配符選擇器
盡可能的少創建jQuery對象
  • document.getElementById('el')$('#el')
  • 如獲取元素id:
$('div').click(function(e) {
    // 生成了個jQuery對象
    var id = $(this).attr('id');
    // 這樣更直接
    var id = this.id;
});
  • 使用鏈式調用緩存jQuery對象
<div id="user" class="none">
    <p class="name"></p>
    <p class="city"></p>
</div>
$('#user')
    .find('.name').html('zhangsan').end()
    .find('.city').html('shenzhen').end()
    .removeClass('none');
  • 做好jQuery對象緩存
var box = $('.box');
box.find('> .cls1');
box.find('> .cls2');
避免頻繁操作DOM
  • 復雜操作把元素從DOM中移除再操作
var $el = $('.box').detach();
var $p = $el.parent();
// do some stuff with $el...
$p.append($el);
  • 在循環外執行DOM修改
// 性能差
$.each(arr, function(i, el) {
    $('.box').prepend($(el));
});
// 較好的做法
var frag = document.createDocumentFragment();
$.each(arr, function(i, el) {
    flag.appendChild(el);
});
$('.box')[0].appendChild(flag);
使用事件代理
$('ul li').on('click', fn);
// better
$('ul').on('click', 'li', fn);

使用事件代理(委托),當有新元素添加進來的時候,不需要再為它綁定事件,這里有demo可以查看效果。

整體優化

  • 雅虎34條:合并壓縮文件和圖片、gzip/deflate、CDN、HTTP頭設置Cache-Control/Expires和Last-Modified/ETag、并行下載與DNS查詢的平衡等
  • 緩存靜態文件,盡可能采用CDN策略,并采用不帶cookie的獨立域名存放,并開啟keep-alive
  • 動態與靜態結合,服務器端拼湊頁面片,最快展現給用戶,縮短白屏時間和頁面可用時間,非首屏數據懶加載
  • 內容分開存放,比如圖片和ajax分別采用不用的服務器(域名下)
  • 保證單個html的http請求數最少
  • 確保網站有favicon.ico文件(瀏覽器會自動請求favicon.ico,如果不存在則會出現大量的404消耗帶寬)
  • 未完待續。。。

【參考文獻】

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容

  • 工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,796評論 2 17
  • 本文轉發自github, 原文地址 <a name='js'>JavaScript</a> 介紹js的基本數據類型...
    XDUZ閱讀 1,054評論 1 11
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進階之旅閱讀 114,512評論 24 450
  • 單例模式 適用場景:可能會在場景中使用到對象,但只有一個實例,加載時并不主動創建,需要時才創建 最常見的單例模式,...
    Obeing閱讀 2,085評論 1 10
  • 看了芒果臺的聲臨其境,只能張著嘴感嘆老師們好厲害。就算只是聽著也是那么的感動,不再是看電視,只需要聽電視就好了。聲...
    LSY米閱讀 162評論 2 1