天天看點

一個合格的中級前端工程師需要掌握的技能筆記(上)

Github來源:一個合格的中級前端工程師需要掌握的技能 | 求星星 ✨ | 給個❤️關注,❤️點贊,❤️鼓勵一下作者

大家好,我是魔王哪吒,很高興認識你~~

哪吒人生信條:如果你所學的東西 處于喜歡 才會有強大的動力支撐。

每天學習程式設計,讓你離夢想更新一步,感謝不負每一份熱愛程式設計的程式員,不論知識點多麼奇葩,和我一起,讓那一顆四處流蕩的心定下來,一直走下去,加油,

2021

加油!歡迎關注加我

vx:xiaoda0423

,歡迎點贊、收藏和評論

不要害怕做夢,但是呢,也不要光做夢,要做一個實幹家,而不是空談家,求真力行。

前言

如果這篇文章有幫助到你,給個❤️關注,❤️點贊,❤️鼓勵一下作者,接收好挑戰了嗎?文章公衆号首發,關注 程式員哆啦A夢 第一時間擷取最新的文章

❤️筆芯❤️~

已閱:

  1. ES6 系列之 let 和 const
  2. ES6 系列之模闆字元串
  3. ES6 系列之箭頭函數
  4. ES6 系列之模拟實作 Symbol 類型
  5. ES6 系列之疊代器與 for of
  6. ES6 系列之模拟實作一個 Set 資料結構
  7. ES6 系列之 WeakMap
  8. ES6 系列之我們來聊聊 Promise
  9. ES6 完全使用手冊
  10. ES6 系列之 defineProperty 與 proxy
  11. ES6 系列之子產品加載方案
  12. ES6 系列之私有變量的實作
  13. 前端,校招,面淘寶,指南
  14. 前端,社招,面淘寶,指南
  15. 你累死累活做業務,績效還不怎麼樣,我隻能幫你到這了……
  16. 淘系前端校招負責人直播答疑文字實錄
  17. 緻2021屆前端同學的一封信|砥砺前行,未來可期!
  18. 面試被問項目經驗不用慌,按這個步驟回答絕對驚豔
  19. 項目不知道如何做性能優化?不妨試一下代碼分割

HTML子產品

HTML 标記包含一些特殊“元素”如 :

<head>,<title>,<body>,<header>,<footer>,<article>,<p>,<p>,<div>,<span>,<img>,<aside>,<audio>,<canvas>,<datalist>,<details>,<embed>,<nav>,<output>,<progress>,<video> 
           

article元素

表示文檔、頁面、應用或網站中的獨立結構,其意在成為可獨立配置設定的或可複用的結構,如在釋出中,它可能是論壇文章、雜志或新聞文章、部落格、使用者送出的評論、互動式元件,或者其他獨立的内容項目。

p元素

表示一個包含在HTML文檔中的獨立部分,它沒有更具體的語義元素來表示,一般來說會有包含一個标題。

aside元素

表示一個和其餘頁面内容幾乎無關的部分,被認為是獨立于該内容的一部分并且可以被單獨的拆分出來而不會使整體受影響。

audio元素

用于在文檔中嵌入音頻内容。

<audio
    controls
    src="/zzz.mp3">
        dada
        <code>audio</code> .
</audio>
           

canvas元素

用來通過JavaScript(Canvas API 或 WebGL API)繪制圖形及圖形動畫。

<canvas id="canvas" width="300" height="300"></canvas>

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'green';
ctx.fillRect(10, 10, 100, 100);
           

datalist元素

包含了一組

<option>

元素,這些元素表示其它表單控件可選值.

<input list="browsers" name="myBrowser" /></label>
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Internet Explorer">
  <option value="Opera">
  <option value="Safari">
</datalist>
           

details元素

可建立一個挂件,僅在被切換成展開狀态時,它才會顯示内含的資訊。

<summary>

元素可為該部件提供概要或者标簽。

<details>
  <summary>System Requirements</summary>
  <p>Requires a computer running an operating system. The computer
  must have some memory and ideally some kind of long-term storage.
  An input device as well as some form of output device is
  recommended.</p>
</details>
           

System Requirements

Requires a computer running an operating system. The computer  must have some memory and ideally some kind of long-term storage.  An input device as well as some form of output device is  recommended.

embed元素

外部内容嵌入元素

progress元素

用來顯示一項任務的完成進度

<progress id="file" max="100" value="70"> 70% </progress>
           

output标簽

表示計算或使用者操作的結果。

nav元素

表示頁面的一部分,其目的是在目前文檔或其他文檔中提供導航連結

表單小部件:

<form action="/my-handling-form-page" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name">
  </div>
  <div>
    <label for="mail">E-mail:</label>
    <input type="email" id="mail">
  </div>
  <div>
    <label for="msg">Message:</label>
    <textarea id="msg"></textarea>
  </div>
</form>
           

單行文本框

<input type="text" id="comment" name="comment" value="I'm a text field">
           

E-mail 位址框

<input type="email" id="email" name="email" multiple>
           

密碼框

<input type="password" id="pwd" name="pwd">
           

搜尋框

<input type="search" id="search" name="search">
           

電話号碼欄:

<input type="tel" id="tel" name="tel">
           

URL 欄:

<input type="url" id="url" name="url">
           

多行文本框:

<textarea cols="30" rows="10"></textarea>
           

複選框:

<input type="checkbox" checked id="carrots" name="carrots" value="carrots">
           

單選按鈕:

<input type="radio" checked id="soup" name="meal">
           

數字:

<input type="number" name="age" id="age" min="1" max="10" step="2">
           

滑塊:

<input type="range" name="beans" id="beans" min="0" max="500" step="10">
           

日期時間選擇器:

<input type="datetime-local" name="datetime" id="datetime">

<input type="month" name="month" id="month">

<input type="time" name="time" id="time">

<input type="week" name="week" id="week">
           

拾色器:

<input type="color" name="color" id="color">
           

檔案選擇器:

<input type="file" name="file" id="file" accept="image/*" multiple>
           

隐藏内容:

<input type="hidden" id="timestamp" name="timestamp" value="6354561">
           
發送表單資料

用戶端/伺服器體系結構

用戶端(通常是web浏覽器)向伺服器發送請求(大多數情況下是Apache、Nginx、IIS、Tomcat等web伺服器),使用HTTP 協定。

在用戶端:定義如何發送資料:

action 屬性-這個屬性定義了發送資料要去的位置。

method屬性-該屬性定義了如何發送資料。

什麼是表單資料校驗?

通路任何一個帶系統資料庫單的網站,你都會發現,當你送出了沒有輸入符合預期格式的資訊的表單時,注冊頁面都會給你一個回報。

  • “該字段是必填的”(該字段不能留白)
  • 請輸入你的電話号碼
  • 請輸入一個合法的郵箱位址
使用正規表達式校驗

示例:

a — 比對一個字元a(不能比對 b,  aa等等.)
abc — 比對 a, 其次 b, 最後  c.
a* — 比對0個或者多個字元 a (+ 代表至少比對一個或者多個).
[^a] — 比對一個字元,但它不能是a.
a|b — 比對一個字元 a 或者 b.
[abc] — 比對一個字元,它可以是a,b或c.
[^abc] — 比對一個字元,但它不可以是a,b或c.
[a-z] — 比對字元範圍 a-z且全部小寫  (你可以使用 [A-Za-z] 涵蓋大小寫, 或 [A-Z] 來限制必須大寫).
a.c — 比對字元 a,中間比對任意一個字元,最後比對字元 c.
a{5} — 比對字元 a五次.
a{5,7} — 比對字元 a五到七次,不能多或者少.
           

AJAX 技術主要依靠 XMLHttpRequest (XHR) DOM 對象。它可以構造 HTTP 請求、發送它們,并擷取請求結果。

表單資料(

application/x-www-form-urlencoded

)由 URL編碼的鍵/值對清單組成。為了傳輸二進制資料,HTTP請求被重新整合成

multipart/form-data

形式。

建構

XMLHttpRequest

:

XMLHttpRequest

是進行 HTTP 請求的最安全和最可靠的方式。

示例:

function sendData(data) {
  var XHR = new XMLHttpRequest();
  var urlEncodedData = "";
  var urlEncodedDataPairs = [];
  var name;

  // 将資料對象轉換為URL編碼的鍵/值對數組。
  for(name in data) {
    urlEncodedDataPairs.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[name]));
  }

  // 将配對合并為單個字元串,并将所有%編碼的空格替換為
  // “+”字元;比對浏覽器表單送出的行為。
  urlEncodedData = urlEncodedDataPairs.join('&').replace(/%20/g, '+');

  // 定義成功資料送出時發生的情況
  XHR.addEventListener('load', function(event) {
    alert('耶! 已發送資料并加載響應。');
  });

  // 定義錯誤提示
  XHR.addEventListener('error', function(event) {
    alert('哎呀!出問題了。');
  });

  // 建立我們的請求
  XHR.open('POST', 'https://example.com/cors.php');

  // 為表單資料POST請求添加所需的HTTP頭
  XHR.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

  // 最後,發送我們的資料。
  XHR.send(urlEncodedData);
}
           
利用FormData對象來處理表單資料請求。

示例:

function sendData(data) {
  var XHR = new XMLHttpRequest();
  var FD  = new FormData();

  // 把我們的資料添加到這個FormData對象中
  for(name in data) {
    FD.append(name, data[name]);
  }

  // 定義資料成功發送并傳回後執行的操作
  XHR.addEventListener('load', function(event) {
    alert('Yeah! 已發送資料并加載響應。');
  });

  // 定義發生錯誤時執行的操作
  XHR.addEventListener('error', function(event) {
    alert('Oops! 出錯了。');
  });

  // 設定請求位址和方法
  XHR.open('POST', 'https://example.com/cors.php');

  // 發送這個formData對象,HTTP請求頭會自動設定
  XHR.send(FD);
}
           

使用綁定到表單元素上的 FormData

<form id="myForm">
  <label for="myName">告訴我你的名字:</label>
  <input id="myName" name="name" value="John">
  <input type="submit" value="送出">
</form>
           

示例:

window.addEventListener("load", function () {
  function sendData() {
    var XHR = new XMLHttpRequest();

    // 我們把這個 FormData 和表單元素綁定在一起。
    var FD  = new FormData(form);

    // 我們定義了資料成功發送時會發生的事。
    XHR.addEventListener("load", function(event) {
      alert(event.target.responseText);
    });

    // 我們定義了失敗的情形下會發生的事
    XHR.addEventListener("error", function(event) {
      alert('哎呀!出了一些問題。');
    });

    // 我們設定了我們的請求
    XHR.open("POST", "https://example.com/cors.php");

    // 發送的資料是由使用者在表單中提供的
    XHR.send(FD);
  }

  // 我們需要擷取表單元素
  var form = document.getElementById("myForm");

  // ...然後接管表單的送出事件
  form.addEventListener("submit", function (event) {
    event.preventDefault();

    sendData();
  });
});
           

CORS

處理跨域圖檔

通過搭配

crossorigin

屬性和适當的

CORS

标頭,在

<img>

元素中定義的圖檔可以從外部來源加載并在

<canvas>

元素中使用,就像是從本地源加載一樣。

啟用了

CORS

的圖檔

盡管不通過 CORS 就可以在

<canvas>

中使用其他來源的圖檔,但是這會污染畫布,并且不再認為是安全的畫布,這将可能在

<canvas>

檢索資料過程中引發異常。

在"被污染"的畫布中調用以下方法:

  • <canvas>

    的上下文上調用

    getImageData()

    • <canvas>

      上調用

      toBlob()

  • <canvas>

    上調用  

    toDataURL()

CORS

設定屬性

一些提供了對

CORS

的支援的

HTML

元素,比如

<img>

<video>

,具有

crossorigin

元素屬性/

attribute

crossOrigin

對象屬性/

property

),該屬性能使你配置其跨域擷取資源的請求。

CanvasRenderingContext2D.getImageData()

CanvasRenderingContext2D.getImageData()

傳回一個

ImageData

對象,用來描述

canvas

區域隐含的像素資料,這個區域通過矩形表示,

起始點為(sx, sy)、寬為sw、高為sh

文法

ImageData ctx.getImageData(sx, sy, sw, sh);

sx
将要被提取的圖像資料矩形區域的左上角 x 坐标。

sy
将要被提取的圖像資料矩形區域的左上角 y 坐标。

sw
将要被提取的圖像資料矩形區域的寬度。

sh
将要被提取的圖像資料矩形區域的高度。

傳回值
一個ImageData 對象,包含canvas給定的矩形圖像資料。
           

使用 getImageData 方法:

<canvas id="canvas"></canvas>

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.rect(10, 10, 100, 100);
ctx.fill();

console.log(ctx.getImageData(50, 50, 100, 100));
// ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }

傳回值
一個ImageData 對象,包含canvas給定的矩形圖像資料。
           

HTMLCanvasElement.toBlob()

HTMLCanvasElement.toBlob()

方法創造

Blob

對象,用以展示

canvas

上的圖檔;這個圖檔檔案可以被緩存或儲存到本地,由使用者代理端自行決定。如不特别指明,圖檔的類型預設為

image/png

,分辨率為

96dpi

文法

canvas.toBlob(callback, type, encoderOptions);

callback
回調函數,可獲得一個單獨的Blob對象參數。

type 可選
DOMString類型,指定圖檔格式,預設格式為image/png。

encoderOptions 可選
Number類型,值在0與1之間,當請求圖檔格式為image/jpeg或者image/webp時用來指定圖檔展示品質。如果這個參數的值不在指定類型與範圍之内,則使用預設值,其餘參數将被忽略。

傳回值
無。
           

HTMLCanvasElement.toDataURL()

HTMLCanvasElement.toDataURL()

方法傳回一個包含圖檔展示的

data URI

。可以使用

type

參數其類型,預設為

PNG

格式。圖檔的分辨率為

96dpi

  • 如果畫布的高度或寬度是0,那麼會傳回字元串“

    data:,

    ”。
  • 如果傳入的類型非“

    image/png

    ”,但是傳回的值以

    “data:image/png”

    開頭,那麼該傳入的類型是不支援的。
  • Chrome支援“

    image/webp

    ”類型。

文法

canvas.toDataURL(type, encoderOptions);

type 可選
圖檔格式,預設為 image/png

encoderOptions 可選
在指定圖檔格式為 image/jpeg 或 image/webp的情況下,可以從 0 到 1 的區間内選擇圖檔的品質。如果超出取值範圍,将會使用預設值 0.92。其他參數會被忽略。

傳回值
包含 data URI 的DOMString。
           

示例:

<canvas id="canvas" width="5" height="5"></canvas>

var canvas = document.getElementById("canvas");
var dataURL = canvas.toDataURL();
console.log(dataURL);
// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
           

設定圖檔的品質:

var fullQuality = canvas.toDataURL("image/jpeg", 1.0);
// data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...9oADAMBAAIRAxEAPwD/AD/6AP/Z"
var mediumQuality = canvas.toDataURL("image/jpeg", 0.5);
var lowQuality = canvas.toDataURL("image/jpeg", 0.1);
           
允許浏覽器在下載下傳圖像資料時允許跨域通路請求

使用者點選 "Download" 按鈕時開始下載下傳:

function startDownload() {
  let imageURL = "https://xxxx";

  downloadedImg = new Image;
  downloadedImg.crossOrigin = "Anonymous";
  downloadedImg.addEventListener("load", imageReceived, false);
  downloadedImg.src = imageURL;
}
           

canvas

toDataURL()

方法用于将圖像轉換為

data:// URL

形式的

PNG

格式圖檔

通過

rel="preload"

進行内容預加載

<link>

标簽最常見的應用情形就是被用來加載

CSS

檔案,進而裝飾你的頁面:

<link rel="stylesheet" href="styles/main.css" target="_blank" rel="external nofollow" >

<link rel="preload" href="style.css" target="_blank" rel="external nofollow"  as="style">
<link rel="preload" href="main.js" target="_blank" rel="external nofollow"  as="script">
           
哪些類型的内容可以被預加載?
audio: 音頻檔案。
document: 一個将要被嵌入到<frame>或<iframe>内部的HTML文檔。
embed: 一個将要被嵌入到<embed>元素内部的資源。
fetch: 那些将要通過fetch和XHR請求來擷取的資源,比如一個ArrayBuffer或JSON檔案。
font: 字型檔案。
image: 圖檔檔案。
object: 一個将會被嵌入到<embed>元素内的檔案。
script: JavaScript檔案。
style: 樣式表。
track: WebVTT檔案。
worker: 一個JavaScript的web worker或shared worker。
video: 視訊檔案。
           
如何制作快速加載的HTML頁面
  1. 減小頁面的大小。
  2. 最小化檔案數量:減少一個頁面引用的檔案數量可以降低在下載下傳一個頁面的過程中需要的HTTP請求數量,進而減少這些請求的收發時間。
  3. 使用 CDN。
  4. 減少域名查找:每個獨立的域名都會消耗DNS查找的時間,頁面加載時間會随着獨立域名數量、CSS連結數量、JavaScript還有圖檔資源的數量增加而增加。
  5. 緩存重用的内容:確定任何内容可以被緩存,并且擁有一個合理的有效期。
  6. 高效地排列頁面元件。
  7. 減少内聯腳本的數量。
網頁中添加矢量圖形
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

示例:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Vector versus raster</title>
  </head>
  <body>
    <h1>Vector versus raster</h1>

    <img src="star.png" alt="A raster star">
    <img src="star.svg" alt="A vector star">
  </body>
</html>
           

建立一個圓和一個矩形:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

<svg version="1.1"
     baseProfile="full"
     width="300" height="200"
     xmlns="http://www.w3.org/2000/svg">
  <rect width="100%" height="100%" fill="black" />
  <circle cx="150" cy="100" r="90" fill="blue" />
</svg>
           

示例:

<img
    src="equilateral.svg"
    alt="triangle with all three sides equal"
    height="87px"
    width="100px" />
           
<svg width="300" height="200">
    <rect width="100%" height="100%" fill="green" />
</svg>
           

使用SVG:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

<svg width="100%" height="100%">
<rect width="100%" height="100%" fill="red" />
<circle cx="100%" cy="100%" r="150" fill="blue" stroke="black" />
<polygon points="120,0 240,225 0,225" fill="green"/>
<text x="50" y="100" font-family="Verdana" font-size="55"
      fill="white" stroke="black" stroke-width="2">
        Hello!
</text>
</svg>
           

CSS子產品

外邊距重疊

塊的上外邊距

(margin-top)

和下外邊距

(margin-bottom)

有時合并(折疊)為單個邊距,其大小為單個邊距的最大值(或如果它們相等,則僅為其中一個),這種行為稱為邊距折疊。

布局和包含塊

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

層疊上下文

滿足以下任意一個條件的元素形成:

  • 文檔根元素(

    <html>

    );
  • position

    值為

    absolute

    (絕對定位)或  

    relative

    (相對定位)且

    z-index

    值不為

    auto

    的元素;
  • position

    值為

    fixed

    (固定定位)或

    sticky

    (粘滞定位)的元素(沾滞定位适配所有移動裝置上的浏覽器,但老的桌面浏覽器不支援);
  • flex (

    flexbox

    ) 容器的子元素,且

    z-index

    值不為 auto;
  • grid (

    grid

    ) 容器的子元素,且

    z-index

    值不為 auto;
  • opacity

    屬性值小于 1 的元素
塊格式化上下文

塊格式化上下文(

Block Formatting Context,BFC

) 是Web頁面的可視CSS渲染的一部分,是塊盒子的布局過程發生的區域,也是浮動元素與其他元素互動的區域。

會建立塊格式化上下文:

  • 根元素(

    <html>

  • 浮動元素(元素的

    float

    不是

    none

  • 絕對定位元素(

    元素的 position 為 absolute 或 fixed

  • 行内塊元素(元素的

    display 為 inline-block

  • 表格單元格(元素的

    display 為 table-cell

    ,HTML表格單元格預設為該值)
  • 表格标題(元素的

    display 為 table-caption

    ,HTML表格标題預設為該值)
  • contain

    值為

    layout、content 或 paint

    的元素
  • 彈性元素(

    display 為 flex 或 inline-flex

    元素的直接子元素)
  • 網格元素(

    display 為 grid 或 inline-grid

    元素的直接子元素)

使用

overflow: auto

建立一個會包含這個浮動的

BFC

,通常的做法是設定父元素

overflow: auto

或者設定其他的非預設的

overflow: visible

的值。

設定

overflow: auto

建立一個新的

BFC

來包含這個浮動。我們的

<div>

元素現在變成布局中的迷你布局。任何子元素都會被包含進去。

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

CSS 彈性盒子布局

此屬性是以下CSS屬性的簡寫:

  • flex-grow

  • flex-shrink

  • flex-basis

flex-shrink

屬性指定了

flex

元素的收縮規則。

flex

元素僅在預設寬度之和大于容器的時候才會發生收縮,其收縮的大小是依據

flex-shrink

的值。

flex-shrink: 2;
flex-shrink: 0.6;

/* Global values */
flex-shrink: inherit;
flex-shrink: initial;
flex-shrink: unset
           

flex-grow

設定了一個

flex

項主尺寸的

flex

增長系數。它指定了

flex

容器中剩餘空間的多少應該配置設定給項目(

flex

增長系數)。

主尺寸是項的寬度或高度,這取決于

flex-direction

值。

flex-basis

指定了

flex

元素在主軸方向上的初始大小。如果不使用  

box-sizing

改變盒模型的話,那麼這個屬性就決定了

flex

元素的内容盒(

content-box

)的尺寸。

flex-wrap

指定

flex

元素單行顯示還是多行顯示 。如果允許換行,這個屬性允許你控制行的堆疊方向。

order

屬性規定了彈性容器中的可伸縮項目在布局時的順序。元素按照

order

屬性的值的增序進行布局。擁有相同

order

屬性值的元素按照它們在源代碼中出現的順序進行布局。

flex-flow

屬性是

flex-direction

flex-wrap

的簡寫。

flex-direction: row
flex-wrap: nowrap
           
對齊屬性

align-content

屬性設定了浏覽器如何沿着彈性盒子布局的縱軸和網格布局的主軸在内容項之間和周圍配置設定空間。

/* 基本位置對齊 */
/*align-content不采用左右值 */
align-content: center;     /* 将項目放置在中點 */
align-content: start;      /* 最先放置項目 */
align-content: end;        /* 最後放置項目 */
align-content: flex-start; /* 從起始點開始放置flex元素 */
align-content: flex-end;   /* 從終止點開始放置flex元素 */

/* 預設對齊 */
align-content: normal;

/*基線對齊*/
align-content: baseline;
align-content: first baseline;
align-content: last baseline;

/* 分布式對齊 */
align-content: space-between; /* 均勻分布項目
                                 第一項與起始點齊平,
                                 最後一項與終止點齊平 */
align-content: space-around;  /* 均勻分布項目
                                 項目在兩端有一半大小的空間*/
align-content: space-evenly;  /* 均勻分布項目
                                 項目周圍有相等的空間 */
align-content: stretch;       /* 均勻分布項目
                                 拉伸‘自動’-大小的項目以充滿容器 */

/* 溢出對齊 */
align-content: safe center;
align-content: unsafe center;

/* 全局屬性 */
align-content: inherit; /* 繼承 */
align-content: initial;  /* 初始值 */
align-content: unset; /* 未設定 */
           
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

align-items

示例:

align-items: stretch;

align-items: center;

align-items: start;

align-items: end;
           

align-self: stretch;

效果如下:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

align-self: center;

效果如下:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

align-self: start;

效果如下:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

align-self: end;

效果如下:

一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

justify-content

justify-content: center;     /* 居中排列 */
justify-content: start;      /* Pack items from the start */
justify-content: end;        /* Pack items from the end */
justify-content: flex-start; /* 從行首起始位置開始排列 */
justify-content: flex-end;   /* 從行尾位置開始排列 */
justify-content: left;       /* Pack items from the left */
justify-content: right;      /* Pack items from the right */

justify-content: space-between;  /* 均勻排列每個元素
                                   首個元素放置于起點,末尾元素放置于終點 */
justify-content: space-around;  /* 均勻排列每個元素
                                   每個元素周圍配置設定相同的空間 */
justify-content: space-evenly;  /* 均勻排列每個元素
                                   每個元素之間的間隔相等 */
justify-content: stretch;       /* 均勻排列每個元素
                                   'auto'-sized 的元素會被拉伸以适應容器的大小 */
           

place-content

屬性是

align-content

justify-content

的簡寫

animation

  • animation-name
  • animation-duration
  • animation-timing-function
  • animation-delay
  • animation-iteration-count
  • animation-direction
  • animation-fill-mode
  • animation-play-state
animation: 3s ease-in 1s infinite reverse both running slidein;

animation: 3s linear 1s infinite running slidein;

animation: 3s linear 1s infinite alternate slidein;

animation: .5s linear 1s infinite alternate slidein;

@keyframes slidein {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
           
  • animation-name: none

  • animation-duration: 0s

  • animation-timing-function: ease

  • animation-delay: 0s

  • animation-iteration-count: 1

  • animation-direction: normal

  • animation-fill-mode: none

  • animation-play-state: running

長度機關

css中有兩種長度:相對長度和絕對長度。絕對長度不依賴于其他任何量度。絕對量度無論其所應用的環境如何都保持其長度。

相對長度依賴于使用的環境,如計算機顯示器的螢幕分辨率或字型的大小。

絕對長度根據實際機關定義,如英寸,厘米和點等。

長度機關分相對長度機關和絕對長度機關:相對/絕對

  • 相對長度機關。相對長度機關分:相對字型長度機關和相對視區長度機關
  • 相對字型長度機關,

    如em和ex,還有css3的rem和ch

  • 相對視區長度機關,如

    vh, vw, vmin, vmax

  • 絕對長度機關,常見有

    px,pt,cm,mm,pc

css

中的機關:

時間機關

s,ms

,角度機關

deg,rad

,長度機關

px,em

%

不是長度機關

選擇器:1,類選擇器,2,ID選擇器,3,屬性選擇器,4,僞類選擇器,5,僞元素選擇器。

:first-child
:last-child
::first-line
::first-letter
::before
::after
           

關系選擇器:1,後代選擇器,2,相鄰後代選擇器,3,兄弟選擇器,4,相鄰兄弟選擇器。

規則:

@

@規則指的是以@字元開始的一些規則,如@media, @font-face, @page, @support
           
塊級元素和

display為block

的元素不是一個概念。

so,清除浮動:✍

.clear:after {
 content: '',
 display: table; // 可以是block, list-item
 clear: both;
}
           

不使用

list-item

是:

  1. 第一它字元比較多
  2. 會出現不需要的項目符号
  3. IE浏覽器不支援僞元素的

    display

    指為

    list-item

    ,主要是相容性不好。對于IE浏覽器,普通元素設定

    display:list-item

    有效的,但

    :before/:after

    僞元素就無效了。
塊級盒子就負責結構,内聯盒子就負責内容。

a标簽元素預設display是inline,設定display:block為塊狀化,後面

width: 100%

就沒有問題。

box-sizing

box-sizing

盒尺寸,

width

作用的細節,

box-sizing

屬性的作用是改變

width

的作用細節。内在盒子的4個盒子:

  1. content box
  2. padding box
  3. border box
  4. margin box

預設情況下,width是作用在

content box

上的,

box-sizing

的作用就是可以把

width

作用的盒子變成其他幾個。

理論上寫法:✍

.box1 { box-sizing: content-box; }
.box2 { box-sizing: padding-box; }
.box3 { box-sizing: border-box; }
.box4 { box-sizing: margin-box; }
           

不過隻能寫以下寫法:✍

.box1 { box-sizing: content-box; } // 預設值
.box2 { box-sizing: padding-box; } // 曾經支援
.box3 { box-sizing: border-box; } // 支援
.box4 { box-sizing: margin-box; } // 從未支援
           
建議不要全局重置的做法。這種容易産生沒必要的消耗,這種做法并不能解決所有問題。

*

通配符盡量不使用,因為它會選擇所有标簽元素,對于普通内聯元素,

box-sizing

無論是什麼值,對其渲染表現都沒有影響。同樣有些元素,其預設的

box-sizing

就是

border-box

,是以也沒有必要的消耗。

Internet

工作原理

在浏覽器中輸入Internet位址會發生什麼情況:

  1. 在浏覽器中輸入www位址
  2. 浏覽器與該位址的HTTP伺服器進行互動
  3. HTTP伺服器接收浏覽器的請求
  4. HTTP伺服器查找web文檔
  5. HTTP伺服器發送Web文檔
  6. 浏覽器接收該文檔
  7. 浏覽器處理源代碼
  8. 浏覽器顯示網頁

伺服器端電腦包含了用來處理所有web頁面請求的http伺服器軟體。在浏覽器中輸入internet位址時,浏覽器發出一個請求,經過很長的計算機網絡傳播,直到找到遠端計算機的位址。在請求到達HTTP伺服器後,HTTP伺服器分析該請求,在伺服器的硬碟上搜尋請求的頁面,并對該請求做出響應,傳回所需的web頁面。

響應經過另一條計算機鍊進行傳播,一直到達您的計算機。然後浏覽器打開該響應并讀取HTTP伺服器送回内容。如果伺服器發送的是浏覽器能夠分析的HTML文檔或其他文檔,則浏覽器會讀取該文檔的源代碼并處理成可顯示的web頁面。

  • 樣式表是由規則組成的
  • 規則由選擇器和聲明組成。
  • 聲明由屬性和值組成。
  • 值可以是關鍵字,長度,顔色,字元串,整型,實型,或者是URL。
  • em量度最好用于螢幕布局。
  • URI用于在CSS中包含樣式表和背景圖像。
  • 可以使用style屬性直接在HTML元素中内聯地包含樣式。
選擇器
  • 類和ID選擇器
  • 通用選擇器
  • 後代選擇器
  • 直接子選擇器
  • 相鄰選擇器
  • 屬性選擇器
  • 僞元素
  • 僞類
基于屬性值的選擇

屬性值選擇器基于屬性的存在性和值應用樣式聲明。

input[type="text"]{
 background: blue;
 color: white;
 border: 3px solid royalblue;
}
<input type="text" name="first_name" value="name" size="25"/>
           
屬性子字元串選擇器

出現在另一個字元串中的字元串被稱為字元串。

a[href^="ftp://"] {
 background: blue;
 color: white;
 border: 3px solid royalblue;
}
<a href="ftp://ftp.example.com" target="_blank" rel="external nofollow" />dadaqianduan.cn</a>
           

僞類:僞類是用來表示動态事件,狀态改變或者是在文檔中以其他方法不能輕易實作的情況,可能是使用者的滑鼠懸停或單擊某元素。僞類對目标元素出現某種特殊的狀态應用樣式。

動态僞類
  • :link

    ,表示未通路的超連結
  • :visited

    ,表示已通路的超連結
  • :hover

    ,表示滑鼠指針目前停留在該元素上
  • :active

    ,表示使用者正在單擊該元素
a:link {
 color: red;
}
a:visited {
 color: yellow;
}
           

:first-child

結構化僞類隻用于當一個元素是另一個元素的第一個子元素時。

文本屬性
  • letter-spacing

    屬性以及使用它增加和減少單詞字母間隔的方法
  • word-spacing

    屬性以及使用它增加和減少句子中單詞間隔的方法
  • text-indent

    屬性以及使用它控制段落中文本縮進的方法
  • text-align

    屬性以及使用它對齊文檔中的文本的方法
  • text-decoration

    屬性以及使用它對文本加下劃線,上劃線和删除線的方法
  • text-transform

    屬性以及使用它控制文本的大小寫和進行字母大小寫之間轉換的方法
  • white-space

    屬性以及使用它控制文本流及格式的方法。
  1. letter-spacing

    屬性,用來控制字母間隔的屬性。
letter-spacing: normal;
           
  1. word-spacing

    屬性,用來孔子單詞之間的間隔
word-spacing: normal;
           
  1. text-indent

    屬性縮進段落文本
  2. text-align

    屬性對齊文本
  3. text-decoration

    屬性,用來對文本加下劃線,上劃線,删除線。
  4. text-transform

    屬性,用來控制文本的大小寫
#capitalize {
 text-transform: capitalize;
}
#uppercase {
 text-transform: uppercase;
}
#lowercase {
 text-transform: lowercase;
}
           
  1. white-space

    屬性,允許控制

    web

    文檔源代碼的文本格式化
字型屬性
  1. font-family

    屬性指定字型。
  2. font-style

    屬性用來在一種特定字型提供的不同樣式之間切換。
  3. font-weight

    樣式表屬性提供了指定字型粗細的功能。
  4. font-size

    屬性用來控制字型的大小
溢出的内容

css的overflow屬性用來處理易受尺寸限制影響的内容,這些内容很可能溢出尺寸限制的邊界。overflow屬性最常見的兩個作用是當内容超過可用空間時隐藏内容,或者是通過滾動條使多餘的内容可以被通路。

overflow: visible | hidden | scroll | auto
           
三角等圖形繪制
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

div {
 width: 0;
 border: 10px solid;
 border-color: #f30 transparent transparent;
}
           
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

<style type="text/css">
        .div5 {
                width: 0;
                border: 10px solid;
                border-color: #f30 transparent transparent;
        }
        .div1 {
                width: 10px;
                height: 10px;
                border: 10px solid;
                border-color: #f30 transparent transparent;
        }
        .div2 {
                width: 10px;
                height: 10px;
                border: 10px solid;
                border-color: #f30 #00f #396 #0f0;
        }
        .div3 {
                width: 0;
                border-width: 10px 20px;
                border-style: solid;
                border-color: #f30 transparent transparent;
        }
        .div4 {
                width: 0;
                border-width: 10px 20px;
                border-style: solid;
                border-color: #f30 #f30 transparent transparent;
        }
</style>
           
css中舉足輕重的角色
  • line-height

    行高的定義就是兩基線的間距
  • vertical-align

    的預設值就是基線

JavaScript子產品

事件示例:

const btn = document.querySelector('button');

btn.onclick = function() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}
           

Array

建立數組

var fruits = ['Apple', 'Banana'];

console.log(fruits.length);
// 2
           

通過索引通路數組元素

var first = fruits[0];
// Apple

var last = fruits[fruits.length - 1];
// Banana
           

周遊數組

fruits.forEach(function (item, index, array) {
    console.log(item, index);
});
// Apple 0
// Banana 1
           

添加元素到數組的末尾

var newLength = fruits.push('Orange');
// newLength:3; fruits: ["Apple", "Banana", "Orange"]
           

删除數組末尾的元素

var last = fruits.pop(); // remove Orange (from the end)
// last: "Orange"; fruits: ["Apple", "Banana"];
           

删除數組最前面(頭部)的元素

var first = fruits.shift(); // remove Apple from the front
// first: "Apple"; fruits: ["Banana"];
           

添加元素到數組的頭部

var newLength = fruits.unshift('Strawberry') // add to the front
// ["Strawberry", "Banana"];
           

找出某個元素在數組中的索引

fruits.push('Mango');
// ["Strawberry", "Banana", "Mango"]

var pos = fruits.indexOf('Banana');
// 1
           

複制一個數組

var shallowCopy = fruits.slice(); // this is how to make a copy
// ["Strawberry", "Mango"]
           

方法

Array.prototype.pop()

删除數組的最後一個元素,并傳回這個元素。

Array.prototype.push()

在數組的末尾增加一個或多個元素,并傳回數組的新長度。

Array.prototype.reverse()

颠倒數組中元素的排列順序,即原先的第一個變為最後一個,原先的最後一個變為第一個。

Array.prototype.shift()

删除數組的第一個元素,并傳回這個元素。

Array.prototype.sort()

對數組元素進行排序,并傳回目前數組。

Array.prototype.splice()

在任意的位置給數組添加或删除任意個元素。

Array.prototype.unshift()

在數組的開頭增加一個或多個元素,并傳回數組的新長度。

Array.prototype.concat()

傳回一個由目前數組和其它若幹個數組或者若幹個非數組值組合而成的新數組。

Array.prototype.join()

連接配接所有數組元素組成一個字元串。

Array.prototype.slice()

抽取目前數組中的一段元素組合成一個新數組。

Array.prototype.toString()

傳回一個由所有數組元素組合而成的字元串。遮蔽了原型鍊上的

Object.prototype.toString()

方法。

Array.prototype.indexOf()

傳回數組中第一個與指定值相等的元素的索引,如果找不到這樣的元素,則傳回

-1

Array.prototype.lastIndexOf()

傳回數組中最後一個(從右邊數第一個)與指定值相等的元素的索引,如果找不到這樣的元素,則傳回 -1。

Array.prototype.forEach()

為數組中的每個元素執行一次回調函數。

Array.prototype.every()

如果數組中的每個元素都滿足測試函數,則傳回 true,否則傳回 false。

Array.prototype.some()

如果數組中至少有一個元素滿足測試函數,則傳回 true,否則傳回 false。

Array.prototype.filter()

将所有在過濾函數中傳回 true 的數組元素放進一個新數組中并傳回。

Array.prototype.map()

傳回一個由回調函數的傳回值組成的新數組。

Array.prototype.reduce()

reduce()

方法對數組中的每個元素執行一個由您提供的

reducer

函數(升序執行),将其結果彙總為單個傳回值。

const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;

// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10

// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
           

Array.prototype.reduceRight()

reduceRight()

方法接受一個函數作為累加器(accumulator)和數組的每個值(從右到左)将其減少為單個值。

const array1 = [[0, 1], [2, 3], [4, 5]].reduceRight(
  (accumulator, currentValue) => accumulator.concat(currentValue)
);

console.log(array1);
// expected output: Array [4, 5, 2, 3, 0, 1]
           

Boolean

Boolean

對象是一個布爾值的對象包裝器。

0,-0,null,false,NaN,undefined

,或空字元串(

""

),該對象具有的初始值

false

其值不是

undefined或null

的任何對象在傳遞給條件語句時都将計算為true。

var x = new Boolean(false);
if (x) {
  // 這裡的代碼會被執行
}

var x = false;
if (x) {
  // 這裡的代碼不會執行
}

var x = Boolean(expression);     // 推薦
var x = !!(expression);          // 推薦
var x = new Boolean(expression); // 不太好
           

Boolean.prototype.toString()

根據對象的值傳回字元串

"true"或"false"

。重寫

Object.prototype.toString()

方法。

Boolean.prototype.valueOf()

傳回

Boolean

對象的原始值。重寫

Object.prototype.valueOf()

方法。

Date

建立一個 JavaScript Date 執行個體,該執行個體呈現時間中的某個時刻。
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
           
建立一個新

Date

對象的唯一方法是通過new 操作符,例如:

let now = new Date();

若将它作為正常函數調用(即不加

new

操作符),将傳回一個字元串,而非

Date

對象。

Date()

構造函數有四種基本形式

year
表示年份的整數值。

monthIndex
表示月份的整數值,從 0(1月)到 11(12月)。

date
表示一個月中的第幾天的整數值,從1開始。預設值為1。

hours
表示一天中的小時數的整數值 (24小時制)。預設值為0(午夜)。

minutes
表示一個完整時間(如 01:10:00)中的分鐘部分的整數值。預設值為0。

seconds
表示一個完整時間(如 01:10:00)中的秒部分的整數值。預設值為0。

milliseconds 
表示一個完整時間的毫秒部分的整數值。預設值為0。
           

執行個體方法

Date.prototype.getDate()

根據本地時間傳回指定日期對象的月份中的第幾天(1-31)。

Date.prototype.getDay()

根據本地時間傳回指定日期對象的星期中的第幾天(0-6)。

Date.prototype.getFullYear()

根據本地時間傳回指定日期對象的年份(四位數年份時傳回四位數字)。

Date.prototype.getHours()

根據本地時間傳回指定日期對象的小時(0-23)。

Date.prototype.getMilliseconds()

根據本地時間傳回指定日期對象的毫秒(0-999)。

Date.prototype.getMinutes()

根據本地時間傳回指定日期對象的分鐘(0-59)。

Date.prototype.getMonth()

根據本地時間傳回指定日期對象的月份(0-11)。

Date.prototype.getSeconds()

根據本地時間傳回指定日期對象的秒數(0-59)。

Date.prototype.getTime()

傳回從

1970-1-1 00:00:00 UTC

(協調世界時)到該日期經過的毫秒數,對于

1970-1-1 00:00:00 UTC

之前的時間傳回負值。

Function

Function.prototype.apply()

Function.prototype.bind()

Function.prototype.call()

Function.prototype.toString()
           

JSON

JSON.parse()

JSON.stringify()
           

Math

方法
Math.abs(x)
傳回一個數的絕對值。
Math.acos(x)
傳回一個數的反餘弦值。
Math.acosh(x)
傳回一個數的反雙曲餘弦值。
Math.asin(x)
傳回一個數的反正弦值。
Math.asinh(x)
傳回一個數的反雙曲正弦值。
Math.atan(x)
傳回一個數的反正切值。
Math.atanh(x)
傳回一個數的反雙曲正切值。
Math.atan2(y, x)
傳回 y/x 的反正切值。
Math.cbrt(x)
傳回一個數的立方根。
Math.ceil(x)
傳回大于一個數的最小整數,即一個數向上取整後的值。
Math.clz32(x)
傳回一個 32 位整數的前導零的數量。
Math.cos(x)
傳回一個數的餘弦值。
Math.cosh(x)
傳回一個數的雙曲餘弦值。
Math.exp(x)
傳回歐拉常數的參數次方,Ex,其中 x 為參數,E 是歐拉常數(2.718...,自然對數的底數)。
Math.expm1(x)
傳回 exp(x) - 1 的值。
Math.floor(x)
傳回小于一個數的最大整數,即一個數向下取整後的值。
Math.fround(x)
傳回最接近一個數的單精度浮點型表示。
Math.hypot([x[, y[, …]]])
傳回其所有參數平方和的平方根。
Math.imul(x, y)
傳回 32 位整數乘法的結果。
Math.log(x)
傳回一個數的自然對數(㏒e,即 ㏑)。
Math.log1p(x)
傳回一個數加 1 的和的自然對數(㏒e,即 ㏑)。
Math.log10(x)
傳回一個數以 10 為底數的對數。
Math.log2(x)
傳回一個數以 2 為底數的對數。
Math.max([x[, y[, …]]])
傳回零到多個數值中最大值。
Math.min([x[, y[, …]]])
傳回零到多個數值中最小值。
Math.pow(x, y)
傳回一個數的 y 次幂。
Math.random()
傳回一個 0 到 1 之間的僞随機數。
Math.round(x)
傳回四舍五入後的整數。
Math.sign(x)
傳回一個數的符号,得知一個數是正數、負數還是 0。
Math.sin(x)
傳回一個數的正弦值。
Math.sinh(x)
傳回一個數的雙曲正弦值。
Math.sqrt(x)
傳回一個數的平方根。
Math.tan(x)
傳回一個數的正切值。
Math.tanh(x)
傳回一個數的雙曲正切值。
Math.toSource()
傳回字元串 "Math"。
Math.trunc(x)
傳回一個數的整數部分,直接去除其小數點及之後的部分。
           

Number

方法
Number.isNaN()
确定傳遞的值是否是 NaN。
Number.isFinite()
确定傳遞的值類型及本身是否是有限數。
Number.isInteger()
确定傳遞的值類型是“number”,且是整數。

Number.parseFloat()
和全局對象 parseFloat() 一樣。
Number.parseInt()
和全局對象 parseInt() 一樣。
           

Object

Object

構造函數建立一個對象包裝器。

Object.assign()
通過複制一個或多個對象來建立一個新的對象。

Object.create()
使用指定的原型對象和屬性建立一個新對象。

Object.defineProperty()
給對象添加一個屬性并指定該屬性的配置。

Object.defineProperties()
給對象添加多個屬性并分别指定它們的配置。

Object.entries()
傳回給定對象自身可枚舉屬性的 [key, value] 數組。

Object.freeze()
當機對象:其他代碼不能删除或更改任何屬性。

Object.getOwnPropertyDescriptor()
傳回對象指定的屬性配置。

Object.getOwnPropertyNames()
傳回一個數組,它包含了指定對象所有的可枚舉或不可枚舉的屬性名。

Object.getOwnPropertySymbols()
傳回一個數組,它包含了指定對象自身所有的符号屬性。

Object.getPrototypeOf()
傳回指定對象的原型對象。

Object.is()
比較兩個值是否相同。

Object.isExtensible()
判斷對象是否可擴充。

Object.isFrozen()
判斷對象是否已經當機。

Object.isSealed()
判斷對象是否已經密封。

Object.setPrototypeOf()
設定對象的原型(即内部 [[Prototype]] 屬性)。
           

WeakMap

WeakMap

對象是一組鍵/值對的集合,其中的鍵是弱引用的。其鍵必須是對象,而值可以是任意的。

WeakSet

WeakSet

對象允許你将弱保持對象存儲在一個集合中。

文法

new WeakSet([iterable]);
           

instanceof

instanceof

運算符用于檢測構造函數的

prototype

屬性是否出現在某個執行個體對象的原型鍊上。

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}
const auto = new Car('2323', '2324', 1234);

console.log(auto instanceof Car);
// expected output: true

console.log(auto instanceof Object);
// expected output: true
           

typeof

typeof

操作符傳回一個字元串,表示未經計算的操作數的類型。

console.log(typeof 42);
// expected output: "number"

console.log(typeof 'blubber');
// expected output: "string"

console.log(typeof true);
// expected output: "boolean"

console.log(typeof undeclaredVariable);
// expected output: "undefined"
           

new

new 運算符建立一個使用者定義的對象類型的執行個體或具有構造函數的内置對象的執行個體。

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const car1 = new Car('sdfs', 'sdfsd sdf', 2234);

console.log(car1.make);
// expected output: "Eagle"
           

Promises/A+

規範
  • fulfill,解決,指一個promise成功時進行一些列操作,如狀态的改變,回調的執行。雖然規範中用fulfill來表示解決,但在後面的promise實作多以resolve來指代。
  • reject,拒絕,指一個promise失敗時進行的一些列操作
  • eventual value,指的是promise被解決時傳遞給解決回調的指,由于promise有一次性的特征,是以當這個值被傳遞時,标志着promise等待态的結束,稱為終值,有時稱為值。
  • reason,拒絕原因,指在promise被拒絕時傳遞給拒絕回調的值。

示例:

var fs = require('fs')
function writeFileAsync(fpath, data, cb) {
 fs.writeFile(fpath, data, function(err) {
  cb(err);
 });
}

var fs = require('fs')
var Promise = require('bluebird');

function writeFileAsync(fpath, data) {
 return new Promise(function(resolve, reject) {
  fs.writeFile(fpath, data, function(err){
   if(err) reject(err)
   else resolve()
  })
 })
}
           
// 回調嵌套
request(url, funcion(err, res, body) {
 if(err) handleError(err)
 
 fs.writeFile('1.txt', body, function(err) {
  if(err) handleError(err)
  request(url2, function(err, res, body) {
   if(err) handleError(err)
  })
 })
})

// Promise寫法
request(url)
 .then(function(result) {
  return wirteFileAsync('1.txt', result)
 })
 .then(function(result) {
  return request(url2)
 })
 .catch(function(e){
  handleError(e)
 })
           

交通燈問題

function red() {
 console.log('red');
}
function green() {
 console.log('green');
}
function yellow() {
 console.log('yellow');
}
var tic = function(timer, cb) {
 return new Promise(function(resolve, reject) {
  setTimeout(function(){
   cb();
   resolve();
  },timer);
 };
};
var d = new Promise(function(resolve, reject){resolve();});
var step = function(def) {
 def.then(function() {
  return tic(3000, red);
 }).then(function() {
  return tic(2000, green);
 }).then(function() {
  return tic(1000, yellow);
 });
}

var d = new Promise(function(resolve, reject) {resolve();});
var step = function(def){
 while(true) {
  def.then(function() {
   return tic(3000, red);
  }).then(function() {
   return tic(2000, green);
  }).then(function() {
   return tic(1000, yellow);
  });
 }
}

var d = new Promise(function(resolve, reject) { resolve();});
var step = function(def) {
 def.then(function() {
  return tic(3000, red);
 }).then(function() {
  return tic(2000, green);
 }).then(function() {
  step(def);
 });
}
           

優化:

var tic = function(timmer, str){
 return new Promise(function(resolve, reject) {
  setTimeout(function() {
   console.log(str);
   resolve(1);
  }, timmer);
 });
};


function *gen(){
 yield tic(3000, 'red');
 yield tic(1000, 'green');
 yield tic(2000, 'yellow');
}

var iterator = gen();
var step = function(gen, iterator){
 var s = iterator.next();
 if (s.done) {
  step(gen, gen());
 } else {
  s.value.then(function() {
   step(gen, iterator);
  });
 }
}

step(gen, iterator);
           
var promise = new Promise(function(resolve) {
 resolve(42);
});
promise.then(function(value) {
 console.log(value);
}).catch(function(error) {
 console.log(error);
});
           

使用了回調函數的異步處理

getAsync("file.txt", function(error, result) {
 if(error){ // 取得失敗時的處理
  throw error;
 }
 // 取得成功時的處理
});
           

使用Promise進行異步處理的一個例子

var promise = getAsyncPromise('fileA.txt');
promise.then(function(result) {
 // 擷取檔案内容成功時的處理
}).catch(function(error) {
 // 擷取檔案内容失敗時的處理
});
           

Constructor

Promise

類似于

XMLHttpRequest

,從構造函數

Promise

來建立一個建立新

promise

對象作為接口。

要想建立一個

promise

對象、可以使用

new

來調用

Promise

的構造器來進行執行個體化。

var promise = new Promise(function(resolve, reject) {
    // 異步處理
    // 處理結束後、調用resolve 或 reject
});
           
promise.then(onFulfilled, onRejected)
           

resolve

(成功)時

onFulfilled

會被調用

reject

(失敗)時

onRejected

會被調用

Promise

的狀态

用new Promise 執行個體化的promise對象有以下三個狀态。

"has-resolution" - Fulfilled

resolve

(成功)時。此時會調用

onFulfilled

"has-rejection" - Rejected

reject

(失敗)時。此時會調用

onRejected

"unresolved" - Pending

既不是

resolve

也不是

reject

的狀态。也就是

promise

對象剛被建立後的初始化狀态等

promise

對象的狀态,從

Pending

轉換為

Fulfilled

Rejected

之後, 這個

promise

對象的狀态就不會再發生任何變化。

也就是說,

Promise

Event

等不同,在

.then

後執行的函數可以肯定地說隻會被調用一次。

建立XHR的promise對象
function getURL(URL) {
 return new Promise(function (resolve, reject) {
  var req = new XMLHttpRequest();
  req.open('GET', URL, true);
  req.onload = function() {
   if(req.status === 200) {
    resolve(req.responseText);
   }else{
    reject(new Error(req.statusText));
   }
  };
  req.onerror = function() {
   reject(new Error(req.statusText));
  };
  req.send();
 });
}
// 運作示例xxx
var URL = "http://x'x'x.org/get";
getURL(URL).then(function onFulfilled(value){
    console.log(value);
}).catch(function onRejected(error){
    console.error(error);
});
           
Promise.resolve(42).then(function(value){
    console.log(value);
});
           
var promise = new Promise(function (resolve){
    console.log("inner promise"); // 1
    resolve(42);
});
promise.then(function(value){
    console.log(value); // 3
});
console.log("outer promise"); // 2

nner promise // 1
outer promise // 2
42            // 3
           

示例:

function taskA() {
    console.log("Task A");
}
function taskB() {
    console.log("Task B");
}
function onRejected(error) {
    console.log("Catch Error: A or B", error);
}
function finalTask() {
    console.log("Final Task");
}

var promise = Promise.resolve();
promise
    .then(taskA)
    .then(taskB)
    .catch(onRejected)
    .then(finalTask);
    
Task A
Task B
Final Task
           
一個合格的中級前端工程師需要掌握的技能筆記(上)

image.png

AMD 與 CMD 的差別
  • CMD 推崇依賴就近,AMD 推崇依賴前置。
  • AMD 是提前執行,CMD 是延遲執行

AMD 和 CMD 都是用于浏覽器端的子產品規範,而在伺服器端比如 node,采用的則是 CommonJS 規範。

CommonJS 規範加載子產品是同步的,也就是說,隻有加載完成,才能執行後面的操作。

AMD規範則是非同步加載子產品,允許指定回調函數。

  1. CommonJS 子產品輸出的是一個值的拷貝,ES6 子產品輸出的是值的引用。
  2. CommonJS 子產品是運作時加載,ES6 子產品是編譯時輸出接口。

CommonJS 加載的是一個對象(即module.exports屬性),該對象隻有在腳本運作完才會生成。而 ES6 子產品不是對象,它的對外接口隻是一種靜态定義,在代碼靜态解析階段就會生成。

CommonJS 子產品輸出的是值的拷貝,也就是說,一旦輸出一個值,子產品内部的變化就影響不到這個值。

如何檢視代碼使用率
  • 打開 Chrome Dev Tool;
  • 按下 Cmd + Shift + P or Ctrl + Shift + P ;
  • 輸入 Coverage,并選擇第一個出現的選項;
使用 Array.includes 來處理多個條件

示例:

function test(fruit) {
  if (fruit == 'apple' || fruit == 'strawberry') {
    console.log('red');
  }
}
           

優化:

function test(fruit) {
  // 條件提取到數組中
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  if (redFruits.includes(fruit)) {
    console.log('red');
  }
}
           
減少嵌套,提前使用 return 語句
function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  // 條件 1:fruit 必須有值
  if (fruit) {
    // 條件 2:必須為紅色
    if (redFruits.includes(fruit)) {
      console.log('red');
 
      // 條件 3:數量必須大于 10
      if (quantity > 10) {
        console.log('big quantity');
      }
    }
  } else {
    throw new Error('No fruit!');
  }
}
 
// 測試結果
test(null); // 抛出錯誤:No fruits
test('apple'); // 列印:red
test('apple', 20); // 列印:red,big quantity
           

優化:

/* 在發現無效條件時提前 return */
 
function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  // 條件 1:提前抛出錯誤
  if (!fruit) throw new Error('No fruit!');
 
  // 條件2:必須為紅色
  if (redFruits.includes(fruit)) {
    console.log('red');
 
    // 條件 3:數量必須大于 10
    if (quantity > 10) {
      console.log('big quantity');
    }
  }
}
           

優化:

/* 在發現無效條件時提前 return */
 
function test(fruit, quantity) {
  const redFruits = ['apple', 'strawberry', 'cherry', 'cranberries'];
 
  if (!fruit) throw new Error('No fruit!'); // 條件 1:提前抛出錯誤
  if (!redFruits.includes(fruit)) return;  // 條件 2:當 fruit 不是紅色的時候,提前 return
 
  console.log('red');
 
  // 條件 3:必須是大量存在
  if (quantity > 10) {
    console.log('big quantity');
  }
}
           
使用函數的預設參數 和 解構

使用 JavaScript 時總是需要檢查

null / undefined

值并配置設定預設值:

function test(fruit, quantity) {
  if (!fruit) return;
  const q = quantity || 1; // 如果沒有提供 quantity 參數,則預設為 1
 
  console.log(`We have ${q} ${fruit}!`);
}
 
// 測試結果
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
           

優化:

function test(fruit, quantity = 1) { // i如果沒有提供 quantity 參數,則預設為 1
  if (!fruit) return;
  console.log(`We have ${quantity} ${fruit}!`);
}
 
// 測試結果
test('banana'); // We have 1 banana!
test('apple', 2); // We have 2 apple!
           
function test(fruit) { 
  // 如果有值,則列印 fruit.name
  if (fruit && fruit.name)  {
    console.log (fruit.name);
  } else {
    console.log('unknown');
  }
}
 
//測試結果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
           

優化:

// 解構 —— 隻獲得 name 屬性
// 參數預設配置設定空對象 {}
function test({name} = {}) {
  console.log (name || 'unknown');
}
 
//測試結果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
           

優化:

// 引入 lodash 庫,我們将獲得 _.get()
function test(fruit) {
  console.log(_.get(fruit, 'name', 'unknown'); // 擷取 name 屬性,如果沒有配置設定,則設為預設值 unknown
}
 
//測試結果
test(undefined); // unknown
test({ }); // unknown
test({ name: 'apple', color: 'red' }); // apple
           
選擇

Map / Object

字面量,而不是

Switch

語句

示例:

function test(color) {
  // 使用 switch case 語句,根據顔色找出對應的水果
  switch (color) {
    case 'red':
      return ['apple', 'strawberry'];
    case 'yellow':
      return ['banana', 'pineapple'];
    case 'purple':
      return ['grape', 'plum'];
    default:
      return [];
  }
}
 
//測試結果
test(null); // []
test('yellow'); // ['banana', 'pineapple']
           

優化:

// 使用對象字面量,根據顔色找出對應的水果
  const fruitColor = {
    red: ['apple', 'strawberry'],
    yellow: ['banana', 'pineapple'],
    purple: ['grape', 'plum']
  };
 
function test(color) {
  return fruitColor[color] || [];
}
           
// 使用 Map ,根據顔色找出對應的水果
  const fruitColor = new Map()
    .set('red', ['apple', 'strawberry'])
    .set('yellow', ['banana', 'pineapple'])
    .set('purple', ['grape', 'plum']);
 
function test(color) {
  return fruitColor.get(color) || [];
}
           
 const fruits = [
    { name: 'apple', color: 'red' }, 
    { name: 'strawberry', color: 'red' }, 
    { name: 'banana', color: 'yellow' }, 
    { name: 'pineapple', color: 'yellow' }, 
    { name: 'grape', color: 'purple' }, 
    { name: 'plum', color: 'purple' }
];
 
function test(color) {
  // 使用 Array filter  ,根據顔色找出對應的水果
 
  return fruits.filter(f => f.color == color);
}
           
使用

Array.every

Array.some

來處理全部/部分滿足條件
const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
  ];
 
function test() {
  let isAllRed = true;
 
  // 條件:所有的水果都必須是紅色
  for (let f of fruits) {
    if (!isAllRed) break;
    isAllRed = (f.color == 'red');
  }
 
  console.log(isAllRed); // false
}
           

優化:

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
  ];
 
function test() {
  // 條件:簡短方式,所有的水果都必須是紅色
  const isAllRed = fruits.every(f => f.color == 'red');
 
  console.log(isAllRed); // false
}
           

使用

Array.some

const fruits = [
    { name: 'apple', color: 'red' },
    { name: 'banana', color: 'yellow' },
    { name: 'grape', color: 'purple' }
];
 
function test() {
  // 條件:是否存在紅色的水果
  const isAnyRed = fruits.some(f => f.color == 'red');
 
  console.log(isAnyRed); // true
}
           

Spread operator

(展開操作符)

示例:

const favoriteFood = ['Pizza', 'Fries', 'Swedish-meatballs'];
 
console.log(...favoriteFood);
//Pizza Fries Swedish-meatballs
           

for…of

疊代器
const toolBox = ['Hammer', 'Screwdriver', 'Ruler']
for(const item of toolBox) {
  console.log(item)
}
 
// Hammer
// Screwdriver
// Ruler
           

Includes()

方法

const garge = ['BMW', 'AUDI', 'VOLVO'];
const findCar = garge.includes('BMW');
console.log(findCar);
 
// true
           
清空或截斷數組
const arr = [11, 22, 33, 44, 55, 66];
// truncanting
arr.length = 3;
console.log(arr); //=> [11, 22, 33]
// clearing
arr.length = 0;
console.log(arr); //=> []
console.log(arr[2]); //=> undefined
           
使用對象解構(

destructuring

)模拟命名參數

示例:

doSomething({ foo: 'Hello', bar: 'Hey!', baz: 42 });
function doSomething(config) {
  const foo = config.foo !== undefined ? config.foo : 'Hi';
  const bar = config.bar !== undefined ? config.bar : 'Yo!';
  const baz = config.baz !== undefined ? config.baz : 13;
  // ...
}
           

優化:

function doSomething({ foo = 'Hi', bar = 'Yo!', baz = 13 } = {}) {
  // ...
}
           
使用

async/await

await

多個

async

函數
await Promise.all([anAsyncCall(), thisIsAlsoAsync(), oneMore()])
           
建立純(

pure

)對象

示例:

const pureObject = Object.create(null);
console.log(pureObject); //=> {}
console.log(pureObject.constructor); //=> undefined
console.log(pureObject.toString); //=> undefined
console.log(pureObject.hasOwnProperty); //=> undefined
           
平鋪多元數組

示例:

// 僅僅适用于二維數組
const arr = [11, [22, 33], [44, 55], 66];
const flatArr = [].concat(...arr); //=> [11, 22, 33, 44, 55, 66]
           

優化:

unction flattenArray(arr) {
  const flattened = [].concat(...arr);
  return flattened.some(item => Array.isArray(item)) ? 
    flattenArray(flattened) : flattened;
}
 
const arr = [11, [22, 33], [44, [55, 66, [77, [88]], 99]]];
const flatArr = flattenArray(arr); 
//=> [11, 22, 33, 44, 55, 66, 77, 88, 99]
           

Array.prototype

Array.prototype

 屬性表示

Array

構造函數的原型,并允許您向所有

Array

對象添加新的屬性和方法。

示例:

/*
如果JavaScript本身不提供 first() 方法,
添加一個傳回數組的第一個元素的新方法。
*/

if(!Array.prototype.first) {
    Array.prototype.first = function() {
        console.log(`如果JavaScript本身不提供 first() 方法,
添加一個傳回數組的第一個元素的新方法。`);
        return this[0];
    }
}
           
Array.isArray(Array.prototype);
// true
           

方法-會改變自身的方法

Array.prototype.pop()
删除數組的最後一個元素,并傳回這個元素。
Array.prototype.push()
在數組的末尾增加一個或多個元素,并傳回數組的新長度。
Array.prototype.reverse()
颠倒數組中元素的排列順序,即原先的第一個變為最後一個,原先的最後一個變為第一個。
Array.prototype.shift()
删除數組的第一個元素,并傳回這個元素。
Array.prototype.sort()
對數組元素進行排序,并傳回目前數組。
Array.prototype.splice()
在任意的位置給數組添加或删除任意個元素。
Array.prototype.unshift()
在數組的開頭增加一個或多個元素,并傳回數組的新長度。
           

不會改變自身的方法

Array.prototype.concat()
傳回一個由目前數組和其它若幹個數組或者若幹個非數組值組合而成的新數組。
Array.prototype.join()
連接配接所有數組元素組成一個字元串。
Array.prototype.slice()
抽取目前數組中的一段元素組合成一個新數組。
Array.prototype.toString()
傳回一個由所有數組元素組合而成的字元串。遮蔽了原型鍊上的 Object.prototype.toString() 方法。
Array.prototype.indexOf()
傳回數組中第一個與指定值相等的元素的索引,如果找不到這樣的元素,則傳回 -1。
Array.prototype.lastIndexOf()
傳回數組中最後一個(從右邊數第一個)與指定值相等的元素的索引,如果找不到這樣的元素,則傳回 -1。
           

周遊方法

Array.prototype.forEach()
為數組中的每個元素執行一次回調函數。
           

Array.from()

Array.from()

方法從一個類似數組或可疊代對象建立一個新的,淺拷貝的數組執行個體。

console.log(Array.from('foo'));
// expected output: Array ["f", "o", "o"]

console.log(Array.from([1, 2, 3], x => x + x));
// expected output: Array [2, 4, 6]
           

文法

Array.from(arrayLike[, mapFn[, thisArg]])

傳回值
一個新的數組執行個體。
           

從 String 生成數組

Array.from('foo');
// [ "f", "o", "o" ]
           

從 Set 生成數組

const set = new Set(['foo', 'bar', 'baz', 'foo']);
Array.from(set);
// [ "foo", "bar", "baz" ]
           

從類數組對象(arguments)生成數組

function f() {
  return Array.from(arguments);
}

f(1, 2, 3);

// [ 1, 2, 3 ]
           

數組去重合并

function combine(){
    let arr = [].concat.apply([], arguments);  //沒有去重複的新數組
    return Array.from(new Set(arr));
}

var m = [1, 2, 2], n = [2,3,3];
console.log(combine(m,n));                     // [1, 2, 3]
           

Array.isArray()

Array.isArray()

用于确定傳遞的值是否是一個 Array。

示例:

Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
           

instanceof 和 isArray

當檢測

Array

執行個體時,

Array.isArray

優于

instanceof

,因為

Array.isArray

能檢測

iframes

.

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr);  // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false
           

Polyfill

示例:

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
           

Array.of()

Array.of()

方法建立一個具有可變數量參數的新數組執行個體,而不考慮參數的數量或類型。

Array.of()

和 Array 構造函數之間的差別在于處理整數參數:

Array.of(7)

建立一個具有單個元素 7 的數組,而

Array(7)

建立一個長度為7的空數組(注意:這是指一個有7個空位(

empty

)的數組,而不是由7個

undefined

組成的數組)。

Array.of(7);       // [7]
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]
           

文法

Array.of(element0[, element1[, ...[, elementN]]])
           

示例

Array.of(1);         // [1]
Array.of(1, 2, 3);   // [1, 2, 3]
Array.of(undefined); // [undefined]
           

相容舊環境

if (!Array.of) {
  Array.of = function() {
    return Array.prototype.slice.call(arguments);
  };
}
           

get Array[@@species]

Array[@@species]

通路器屬性傳回 Array 的構造函數。

文法

Array[Symbol.species]
           

傳回值

Array

的構造函數。

描述

species

通路器屬性傳回

Array

對象的預設構造函數。子類的構造函數可能會覆寫并改變構造函數的指派。

示例

species

屬性傳回預設構造函數, 它用于 Array 對象的構造函數

Array:

Array[Symbol.species]; // function Array()
           
閉包

閉包讓你可以在一個内層函數中通路到其外層函數的作用域。在

JavaScript

中,每當建立一個函數,閉包就會在函數建立的同時被建立出來。

詞法作用域

示例:

function init() {
    var name = "Mozilla"; // name 是一個被 init 建立的局部變量
    function displayName() { // displayName() 是内部函數,一個閉包
        alert(name); // 使用了父函數中聲明的變量
    }
    displayName();
}
init();
           

詞法(

lexical

)一詞指的是,詞法作用域根據源代碼中聲明變量的位置來确定該變量在何處可用。嵌套函數可通路聲明于它們外部作用域的變量。

閉包

示例:

function makeFunc() {
    var name = "Mozilla";
    function displayName() {
        alert(name);
    }
    return displayName;
}

var myFunc = makeFunc();
myFunc();
           

閉包是由函數以及聲明該函數的詞法環境組合而成的。該環境包含了這個閉包建立時作用域内的任何局部變量。

示例:

// add5 和 add10 都是閉包。它們共享相同的函數定義,但是儲存了不同的詞法環境。
function makeAdder(x) {
  return function(y) {
    return x + y;
  };
}

var add5 = makeAdder(5);
var add10 = makeAdder(10);

console.log(add5(2));  // 7
console.log(add10(2)); // 12
           

示例:

function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
  this.getName = function() {
    return this.name;
  };

  this.getMessage = function() {
    return this.message;
  };
}

function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype = {
  getName: function() {
    return this.name;
  },
  getMessage: function() {
    return this.message;
  }
};


function MyObject(name, message) {
  this.name = name.toString();
  this.message = message.toString();
}
MyObject.prototype.getName = function() {
  return this.name;
};
MyObject.prototype.getMessage = function() {
  return this.message;
};
           
繼承與原型鍊

當談到繼承時,

JavaScript

隻有一種結構:對象。每個執行個體對象(

object

)都有一個私有屬性(稱之為

__proto__

)指向它的構造函數的原型對象(

prototype

)。該原型對象也有一個自己的原型對象(

__proto__

) ,層層向上直到一個對象的原型對象為

null

。根據定義,

null

沒有原型,并作為這個原型鍊中的最後一個環節。

幾乎所有

JavaScript

中的對象都是位于原型鍊頂端的

Object

的執行個體。

JavaScript

對象有一個指向一個原型對象的鍊。當試圖通路一個對象的屬性時,它不僅僅在該對象上搜尋,還會搜尋該對象的原型,以及該對象的原型的原型,依次層層向上搜尋,直到找到一個名字比對的屬性或到達原型鍊的末尾。

遵循

ECMAScript

标準,

someObject.[[Prototype]]

符号是用于指向

someObject

的原型。從

ECMAScript 6

開始,

[[Prototype]]

可以通過

Object.getPrototypeOf()

Object.setPrototypeOf()

通路器來通路。這個等同于

JavaScript

的非标準但許多浏覽器實作的屬性

__proto__

示例:

// 讓我們從一個函數裡建立一個對象o,它自身擁有屬性a和b的:
let f = function () {
   this.a = 1;
   this.b = 2;
}
/* 這麼寫也一樣
function f() {
  this.a = 1;
  this.b = 2;
}
*/
let o = new f(); // {a: 1, b: 2}

// 在f函數的原型上定義屬性
f.prototype.b = 3;
f.prototype.c = 4;

// 不要在 f 函數的原型上直接定義 f.prototype = {b:3,c:4};這樣會直接打破原型鍊
// o.[[Prototype]] 有屬性 b 和 c
//  (其實就是 o.__proto__ 或者 o.constructor.prototype)
// o.[[Prototype]].[[Prototype]] 是 Object.prototype.
// 最後o.[[Prototype]].[[Prototype]].[[Prototype]]是null
// 這就是原型鍊的末尾,即 null,
// 根據定義,null 就是沒有 [[Prototype]]。

// 綜上,整個原型鍊如下:

// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null

console.log(o.a); // 1
// a是o的自身屬性嗎?是的,該屬性的值為 1

console.log(o.b); // 2
// b是o的自身屬性嗎?是的,該屬性的值為 2
// 原型上也有一個'b'屬性,但是它不會被通路到。
// 這種情況被稱為"屬性遮蔽 (property shadowing)"

console.log(o.c); // 4
// c是o的自身屬性嗎?不是,那看看它的原型上有沒有
// c是o.[[Prototype]]的屬性嗎?是的,該屬性的值為 4

console.log(o.d); // undefined
// d 是 o 的自身屬性嗎?不是,那看看它的原型上有沒有
// d 是 o.[[Prototype]] 的屬性嗎?不是,那看看它的原型上有沒有
// o.[[Prototype]].[[Prototype]] 為 null,停止搜尋
// 找不到 d 屬性,傳回 undefined
           
繼承方法
var o = {
  a: 2,
  m: function(){
    return this.a + 1;
  }
};

console.log(o.m()); // 3
// 當調用 o.m 時,'this' 指向了 o.

var p = Object.create(o);
// p是一個繼承自 o 的對象

p.a = 4; // 建立 p 的自身屬性 'a'
console.log(p.m()); // 5
// 調用 p.m 時,'this' 指向了 p
// 又因為 p 繼承了 o 的 m 函數
// 是以,此時的 'this.a' 即 p.a,就是 p 的自身屬性 'a' 
           
在 JavaScript 中使用原型
function doSomething(){}
console.log( doSomething.prototype );
// 和聲明函數的方式無關,
// JavaScript 中的函數永遠有一個預設原型屬性。
var doSomething = function(){};
console.log( doSomething.prototype );
           

控制台:

{
    constructor: ƒ doSomething(),
    __proto__: {
        constructor: ƒ Object(),
        hasOwnProperty: ƒ hasOwnProperty(),
        isPrototypeOf: ƒ isPrototypeOf(),
        propertyIsEnumerable: ƒ propertyIsEnumerable(),
        toLocaleString: ƒ toLocaleString(),
        toString: ƒ toString(),
        valueOf: ƒ valueOf()
    }
}
           

給doSomething函數的原型對象添加新屬性,如下:

function doSomething(){}
doSomething.prototype.foo = "bar";
console.log( doSomething.prototype );

{
    foo: "bar",
    constructor: ƒ doSomething(),
    __proto__: {
        constructor: ƒ Object(),
        hasOwnProperty: ƒ hasOwnProperty(),
        isPrototypeOf: ƒ isPrototypeOf(),
        propertyIsEnumerable: ƒ propertyIsEnumerable(),
        toLocaleString: ƒ toLocaleString(),
        toString: ƒ toString(),
        valueOf: ƒ valueOf()
    }
}
           
使用文法結建構立的對象
var o = {a: 1};

// o 這個對象繼承了 Object.prototype 上面的所有屬性
// o 自身沒有名為 hasOwnProperty 的屬性
// hasOwnProperty 是 Object.prototype 的屬性
// 是以 o 繼承了 Object.prototype 的 hasOwnProperty
// Object.prototype 的原型為 null
// 原型鍊如下:
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// 數組都繼承于 Array.prototype
// (Array.prototype 中包含 indexOf, forEach 等方法)
// 原型鍊如下:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}

// 函數都繼承于 Function.prototype
// (Function.prototype 中包含 call, bind等方法)
// 原型鍊如下:
// f ---> Function.prototype ---> Object.prototype ---> null
           
使用構造器建立的對象
function Graph() {
  this.vertices = [];
  this.edges = [];
}

Graph.prototype = {
  addVertex: function(v){
    this.vertices.push(v);
  }
};

var g = new Graph();
// g 是生成的對象,他的自身屬性有 'vertices' 和 'edges'。
// 在 g 被執行個體化時,g.[[Prototype]] 指向了 Graph.prototype。
           
使用 Object.create 建立的對象

可以調用這個方法來建立一個新對象。新對象的原型就是調用

create

方法時傳入的第一個參數:

var a = {a: 1};
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (繼承而來)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因為d沒有繼承Object.prototype
           
使用

class

關鍵字建立的對象

關鍵字包括

class, constructor,static,extends 和 super

示例:

"use strict";

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);
           

❤️關注+點贊+收藏+評論+轉發❤️,原創不易,鼓勵筆者創作更好的文章

點贊、收藏和評論

我是

Jeskson

(達達前端),感謝各位人才的:點贊、收藏和評論,我們下期見!(如本文内容有地方講解有誤,歡迎指出☞謝謝,一起學習了)

我們下期見!

github

收錄,歡迎

Star

:https://github.com/webVueBlog/WebFamily

繼續閱讀