整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          HTML5 的JavaScript 客戶端PDF解決方案-jsPDF

          和往常一樣,jsPDF是一個(gè)開源的客戶端的PDF解決方案,在之前的文章中已經(jīng)介紹過幾個(gè)Web端和PDF相關(guān)的庫,jsPDF同樣是一個(gè)不錯(cuò)的客戶端PDF引 SDK,你可以通過jsPDF在客戶端完成相關(guān)操作,它包含了非常豐富的API,幫助你完成一系列的復(fù)雜操作!可以說它是相當(dāng)領(lǐng)先的HTML5客戶端解決方案了!



          Github

          https://github.com/MrRio/jsPDF

          Github star數(shù)17k+,可以說相當(dāng)受歡迎了!


          安裝使用

          一般情況下我們會(huì)考慮使用包管理,常見的就是npm了,因此安裝非常簡單

          npm install jspdf --save
          

          或者也可以使用yarn

          yarn add jspdf
          

          接下來就是制作你的文件的時(shí)候了

          默認(rèn)導(dǎo)出為a4紙張,縱向,使用毫米表示單位


          var doc = new jsPDF()
          doc.text('Hello world!', 10, 10)
          doc.save('a4.pdf')
          

          如果要更改紙張尺寸,方向或單位,可以執(zhí)行以下操作:


          var doc = new jsPDF({
           orientation: 'landscape',
           unit: 'in',
           format: [4, 2]
          })
          doc.text('Hello world!', 1, 1)
          doc.save('two-by-four.pdf')
          

          使用UTF-8 / TTF

          PDF中的14種標(biāo)準(zhǔn)字體僅限于ASCII代碼頁。如果要使用UTF-8,則必須集成自定義字體,該字體提供所需的字形。jsPDF支持.ttf文件。因此,如果你希望在pdf中使用中文文本,則您的字體必須具有必要的中文字形。因此,請(qǐng)檢查您的字體是否支持所需的字形,否則它將顯示空白而不是文本。



          要將字體添加到j(luò)sPDF,在/fontconverter/fontconverter.html中使用官網(wǎng)提供的fontconverter。fontconverter將創(chuàng)建一個(gè)js文件,其中包含提供的ttf文件的內(nèi)容作為base64編碼的字符串和jsPDF的附加代碼。你只需將生成的js-File添加到項(xiàng)目中即可。然后,就可以在代碼中使用setFont-method并編寫UTF-8編碼文本。



          Angular/Webpack/React等配置

          常規(guī)操作

          import * as jsPDF from 'jspdf'
          

          有些框架,必須像下面這樣

          import jsPDF from 'jspdf';
          


          API

          jsPDF的api非常豐富,在這里就不提供相關(guān)地址了,在Github必然找的到,本文重點(diǎn)不在于介紹jsPDF的用法,將部分API截圖展示,通過名稱大致能猜到一些意思,具體用法需要參考官網(wǎng)文檔:













          從截圖來看,其文檔特別的詳細(xì),具體到每一個(gè)API在js文件的行數(shù),便于閱讀源代碼,包括參數(shù)以及返回值都非常明確:



          在線DEMO

          官方提供了一個(gè)在線demo,可以直接運(yùn)行代碼,感興趣的可以先嘗試一下:



          總結(jié)

          jsPDF是筆者見過類似產(chǎn)品中較為突出的,幾乎涵蓋了所有PDF相關(guān)操作,非常詳細(xì)的文檔也讓開發(fā)者,輕松上手,在線demo還能快速學(xué)習(xí),如果你的項(xiàng)目對(duì)PDF的操作比較多,不妨嘗試下jsPDF,唯一需要注意的就是解決字體問題,但是上文也提到過解決方案,感興趣的可以進(jìn)行體驗(yàn)!

          了保證的可讀性,本文采用意譯而非直譯。

          第1章:JS 簡介

          什么是JavaScript

          JS 是一種用于 web 的腳本語言。JS 誕生于 1995 年,由 **Brendan Eich **一手創(chuàng)建,用于向web頁面添加交互性。那時(shí)的互聯(lián)網(wǎng)還處于起步階段,我們今天看到的大多數(shù)花哨的網(wǎng)頁在那時(shí)候還只是一個(gè)夢。

          在項(xiàng)目經(jīng)理的催促下,Brendan 只有 10 天的時(shí)間來創(chuàng)建一種可以在瀏覽器中運(yùn)行的動(dòng)態(tài)、靈活的語言。他寫出了 JavaScript,一種有點(diǎn)奇怪的編程語言,它參考了 Java、C 和 Scheme。JS 一直名聲不好,因?yàn)樗鼜囊婚_始就有很多怪異的地方。但盡管如此,它還是在名人堂占據(jù)了一席之地,并一直挺到了今天。

          現(xiàn)在,JS 被用來創(chuàng)建整個(gè)應(yīng)用程序,稱為SPA(單頁應(yīng)用程序)。隨著使用量的增加,JS 生態(tài)系統(tǒng)也經(jīng)歷了寒武紀(jì)大爆發(fā)。咱們今天用于開發(fā) JS 的大多數(shù) Web 工具和庫,很多用 JS 寫的。JS 也被用于除前端方面的領(lǐng)域。使用 Node.js 咱們可以創(chuàng)建服務(wù)器端和物聯(lián)網(wǎng)應(yīng)用程序,工業(yè)設(shè)備,以及更多。但最重要的是,單頁應(yīng)用程序是 JS 最突出的用法之一。

          在單頁面應(yīng)用中,JS 負(fù)責(zé)所有的事情,使 UI 流暢,無需任何頁面刷新。從用戶的角度來看,這是對(duì)傳統(tǒng) web 應(yīng)用程序的巨大改進(jìn)。但是,能力越大,責(zé)任越大: JS 對(duì)于大多數(shù)移動(dòng)設(shè)備來說是一個(gè)沉重的負(fù)擔(dān),在設(shè)計(jì)和構(gòu)建時(shí)應(yīng)該格外小心。、

          為什么要學(xué) JavaScript

          今天學(xué)習(xí) JS 并不意味著對(duì)變量和函數(shù)的膚淺理解:還有很多。JS 開發(fā)人員知道閉包、this、new、原型系統(tǒng)和更新的特性。JS 一年比一年流行,功能也逐漸完善。現(xiàn)在幾乎每個(gè)前端開發(fā)人員的工作都需要 JS 知識(shí)。招聘經(jīng)理尋找的不是會(huì)使用 JQ (說到j(luò)Query,它似乎正在慢慢消亡) 的。

          大多數(shù)情況下,你也需要了解學(xué)習(xí) TypeScript, 強(qiáng)調(diào)類型的 JS。前端開發(fā)人員應(yīng)該要理解 JS 的特性,并能夠編寫慣用的、結(jié)構(gòu)良好的 JS 代碼。JS 正在迅速傳播,即使你不喜歡這種語言,在這一點(diǎn)上忽視它也可能對(duì)你的職業(yè)生涯不利。

          第1章:JS 基礎(chǔ)

          JS 目前有 7 種基本類型,如下:

          • String
          • Number
          • Boolean
          • Null
          • Undefined
          • Object
          • Symbol(ES6)

          除了 Object 是復(fù)雜數(shù)據(jù)類型外,其它的 6 種是 JS 的基本數(shù)據(jù)類型。每個(gè) JS 類型都有一個(gè)對(duì)應(yīng)的表示,可以在咱們的代碼中使用,比如字符串:

          var string = "Hello John";
          


          數(shù)字:

          var age = 33;
          


          說到這里,JS 也有算術(shù)運(yùn)算:

          運(yùn)算符運(yùn)算名+加法++自增*乘法**指數(shù)-減--自減/除%取除

          在 JS 中,可以使用 var 關(guān)鍵字將值存儲(chǔ)在變量中,這是聲明變量的最兼容方法:

          var greet = "Hello";
          var year = 89;
          var not = false;
          

          這里說的兼容,是因?yàn)樵?ES6 中我們還有兩個(gè)選擇: let 和 const。舊的瀏覽器可能不支持這些新的關(guān)鍵字,除非使用“轉(zhuǎn)置器”,否則可能會(huì)遇到錯(cuò)誤。在新的瀏覽器中,建議用 let 和 const 。主要有兩個(gè)好處:

          • let 和 const 都有自己的塊作用域
          • const 不能重新分配,也不能重新聲明

          塊作用域是指用 let 或 const 聲明的變量與在封閉或外部塊中聲明的相同變量名不重疊。例如:

          let name = "前端小智";
          {
           let name = "王大冶";
           console.log(name); // "王大冶"
          }
          console.log(name); // "前端小智"
          

          這里的 name 似乎是重復(fù)的,但實(shí)際上是兩個(gè)不同的變量在自己的作用域里。const 具有相同的行為:

          const name = "前端小智";
          {
           const name = "王大冶";
           console.log(name); // "王大冶"
          }
          console.log(name); // "前端小智"
          

          與 var 的行為就與 let 和 const 不一樣了。

          var name = "前端小智";
          {
           var name = "王大冶";
           console.log(name); // "王大冶"
          }
          console.log(name); // "王大冶"
          

          正如前端所說,const 不能被重新分配,也不能在同一個(gè)作用域中重新聲明。如果你嘗試重新聲明一個(gè) const,會(huì)得到 "SyntaxError: Identifier has already been declared"。如果將某個(gè)值重新賦值給同一個(gè) const,會(huì)得到 "TypeError: Assignment to constant variable"錯(cuò)誤。

          const name = "前端小智";
          const name = "王大冶";
          // SyntaxError: Identifier 'name' has already been declared
          

          下面代碼也會(huì)拋出錯(cuò)誤:

          const name = "前端小智";
          name = "王大冶";
          // TypeError: Assignment to constant variable.
          

          但是,請(qǐng)注意,這里所說的 “cons 不能重新分配,也不能重新聲明” 時(shí),并不意味著const是不可變的。

          我自己是一名從事了多年開發(fā)的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年年初我花了一個(gè)月整理了一份最適合2019年學(xué)習(xí)的web前端學(xué)習(xí)干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關(guān)注我的頭條號(hào)并在后臺(tái)私信我:前端,即可免費(fèi)獲取。

          這是初學(xué)者都會(huì)遇到的問題。事實(shí)上,任何稍微復(fù)雜一點(diǎn)的 JS 數(shù)據(jù)結(jié)構(gòu),如數(shù)組或?qū)ο螅词乖诜峙浣o const 時(shí),它們的值或者屬性值是可變的,不可變是指這些復(fù)雜對(duì)象的內(nèi)存地址。

          const person = {
           name: "前端小智",
           age: 21
          };
          person.name = "王大冶";
          console.log(person);
          // {name: "王大冶", age: 21}
          

          const 對(duì)象中的不可變是指什么?下面是數(shù)組:

          const list = [1, 1, 3, 2, 5];
          list.shift();
          console.log(list); // [ 1, 3, 2, 5 ]
          

          同樣,不是不可變。有人說 “const 是不可變” 時(shí),請(qǐng)給他看這些例子。現(xiàn)在回到基礎(chǔ)。除了獨(dú)立變量之外,還可以使用字面量的方式聲明數(shù)組:

          var array = ["Hello", 89, false, true];
          


          從 0 開始的索引可以訪問數(shù)組元素:

          var array = ["Hello", 89, false, true];
          var first = array[0]; // "Hello"
          

          幾乎所有 JS 實(shí)體都附加了一些函數(shù),稱為方法。舉兩個(gè)例子,數(shù)組有很多處理自身的方法

          var array = ["Hello", 89, false, true];
          array.push(99);
          array.shift();
          console.log(array); // [ 89, false, true, 99 ];
          

          對(duì)于字符串也是一樣的:

          var string = "John";
          console.log(string.toUpperCase()); // JOHN
          

          在第 5 章中,你會(huì)知道這些方法從何而來,但這里有一個(gè)提示:它們分別在 Array.prototype和 String.prototype 上定義。除了方法之外,還有一些屬性對(duì)于提取關(guān)于字符串長度的信息非常有用:

          var string = "John";
          console.log(string.length); // 4
          

          或者數(shù)組的長度:

          var array = ["Hello", 89, false, true];
          array.push(99);
          array.shift();
          console.log(array.length); // 4
          

          這些屬性有些特殊,因?yàn)樗鼈儽环Q為 "getters"/"setters"。你可以想象一個(gè)給定的字符串就像一個(gè)附加了一堆方法和屬性的對(duì)象。當(dāng)訪問數(shù)組的長度時(shí),你只需調(diào)用相應(yīng)的 getter。setter 函數(shù)用于設(shè)置操作:

          var array = {
           value: ["Hello", 89, false, true],
           push: function(element) {
           //
           },
           shift: function() {
           //
           },
           get length() {
           // gets the length
           },
           set length(newLen) {
           // sets the length
           }
          };
          // Getter call
          var len = array.length
          // Setter call
          array.length = 50;
          

          現(xiàn)在,咱們已經(jīng)奠定了基礎(chǔ),讓我們仔細(xì)看看對(duì)象,它是最重要的 JS 類型之一。

          站在對(duì)象的肩膀上

          Object 是 JS 中最重要的類型,因此幾乎所有其他實(shí)體都可以從中派生。例如,函數(shù)和數(shù)組是專用對(duì)象。JS 中的對(duì)象是鍵/值對(duì)的容器,如以下示例(字面量形式):

          var obj = {
           name: "John",
           age: 33
          };
          

          還有另一種創(chuàng)建對(duì)象的方法,但它很少見,性能低,請(qǐng)避免使用這種形式:

          var obj = new Object({
           name: "John",
           age: 33
          });
          

          正如你所看到的,對(duì)象是保存值的一種方便方法,稍后可以通過訪問相應(yīng)的屬性來檢索這些值:

          var obj = {
           name: "前端小智",
           age: 26
          };
          console.log(obj.name); // "前端小智"
          

          咱們還可以添加新屬性、刪除或更改它們

          var obj = {
           name: "前端小智",
           age: 26
          };
          obj.address = "王大冶";
          delete obj.name;
          obj.age = 18;
          

          對(duì)象的鍵也可以是字符串,在本例中,我們使用方括號(hào)符號(hào)訪問屬性:

          var obj = {
           name: "前端小智",
           age: 26,
           "complex key": "stuff"
          };
          console.log(obj["complex key"]); // "stuff"
          

          但是,點(diǎn)表示法更常見,除非鍵是復(fù)雜的字符串,否則應(yīng)該選擇傳統(tǒng)的屬性訪問:

          var obj = {
           name: "前端小智",
           age: 26
          };
          console.log(obj.name); // "前端小智"
          

          這是咱們所有需要知道的基本知識(shí),但在 第5章,我們將看到 JS 對(duì)象是非常強(qiáng)大的,可以做更多。現(xiàn)在來看看 JS 函數(shù)。

          5 種不同的 JS 函數(shù)

          幾乎每種編程語言都有函數(shù),JS 也不例外。函數(shù)是可重用的代碼段。考慮以下示例

          function hello(message) {
           console.log(message);
          }
          hello("Hello");
          

          function sum(a, b) {
           return a + b;
          }
          var sum = sum(2, 6);
          

          第一個(gè)函數(shù)打印一個(gè)字符串,第二個(gè)函數(shù)向外部世界返回一個(gè)值。正如你所看到的,函數(shù)可以接受參數(shù),列在函數(shù)“簽名”中:

          // a 和 b 是函數(shù)簽名中的參數(shù)
          function sum(a, b) {
           return a + b;
          }
          

          咱們可以在調(diào)用函數(shù)時(shí)傳遞值:

          // a and b are parameters in the function's signature
          function sum(a, b) {
           return a + b;
          }
          // 2 和 6 是該函數(shù)的參數(shù)
          var sum = sum(2, 6);
          

          用 function 關(guān)鍵字聲明的 JS 函數(shù)是常規(guī)函數(shù),與沒有主體的函數(shù)相反常規(guī)函數(shù)可以呈現(xiàn)多種形式:

          • 命名函數(shù)
          • 匿名函數(shù)
          • 對(duì)象方法
          • 對(duì)象方法簡寫(ES 6)
          • IIFE(立即執(zhí)行函數(shù))

          命名函數(shù)是最傳統(tǒng)的函數(shù)類型:

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

          另一方面,匿名函數(shù)沒有名稱,可以分配給一個(gè)變量供以后使用

          var sum = function(a, b) {
           return a + b;
          };
          

          或者用作其他函數(shù)中的回調(diào):

          var button = document.createElement("button");
          button.addEventListener("click", function(event) {
           // do stuff
          });
          

          函數(shù)也可以存在于對(duì)象中,這種稱為該對(duì)象的方法

          var widget = {
           showModal: function() {
           // do stuff
           }
          };
          widget.showModal();
          

          常規(guī)函數(shù)在默認(rèn)情況下也會(huì)得到一個(gè) this 關(guān)鍵字,它可以根據(jù)調(diào)用函數(shù)的方式賦予不同的含義。在第六章中,我們將詳細(xì)探討這個(gè)主題。現(xiàn)在有一個(gè)簡單的規(guī)則:在一個(gè)對(duì)象內(nèi)部運(yùn)行的函數(shù)有 this 指向包含對(duì)象的指針

          var widget = {
           html: "<div></div>",
           showModal: function() {
           console.log(this.html);
           }
          };
          widget.showModal(); // "<div></div>"
          

          在 ES6 中,你也可以使用對(duì)象方法簡寫:

          var widget = {
           showModal() {
           // object method shortand
           }
          };
          widget.showModal();
          

          最后,IIFE (立即執(zhí)行的函數(shù)):

          var IIFE = (function() {
           // what happens in an IIFE stays in the IIFE
          })();
          

          語法可能看起來有點(diǎn)奇怪,但是 IIFE 非常強(qiáng)大,在第4章會(huì)看到它們。除了常規(guī)函數(shù)外,還有箭頭函數(shù),在 ES6 中添加。箭頭函數(shù)不使用 function 關(guān)鍵字,但它們具有相似的形式:

          • 命名箭頭函數(shù)
          • 匿名箭頭函數(shù)
          • 對(duì)象方法
          • IIFE 箭頭函數(shù)

          箭頭函數(shù)很方便,但我建議不要過度使用它們。這是一個(gè)命名的箭頭函數(shù)。如果沒有參數(shù),可以省略 return 語句并使用圓括號(hào)

          const arrow = () => console.log("Silly me");
          


          如果你需要在箭頭函數(shù)中計(jì)算一些東西或者調(diào)用其他函數(shù),可以用花括號(hào)包含一個(gè)主體

          const arrow = () => {
           const a = callMe();
           const b = callYou();
           return a + b;
          };
          

          花括號(hào)也是定義對(duì)象的字面量形式,這并不意味著咱們可以做類似的事情:

          const arrow = () => {
           a : "hello", 
           b: "world"
          };
          

          這是無效的語法。要從箭頭函數(shù)返回對(duì)象,可以使用圓括號(hào):

          const arrow = () => ({
           a: "hello",
           b: "world"
          });
          console.log(arrow());
          // { a: 'hello', b: 'world' }
          

          或者使用 return 語句:

          const arrow = () => {
           return {
           a: "hello",
           b: "world"
           };
          };
          

          與常規(guī)匿名函數(shù)一樣,也有匿名箭頭函數(shù)。這里有一個(gè)作為回調(diào)傳遞給另一個(gè)函數(shù)

          const arr = [1, 2, 3];
          const res = arr.map(element => element + 1);
          console.log(res); // [ 2, 3, 4 ]
          

          它以 element 為參數(shù),并為每個(gè)數(shù)組元素返回 element +1。如你所見,如果箭頭函數(shù)只有一個(gè)參數(shù),則無需在其周圍加上括號(hào):

          const fun = singleParameter => singleParameter + 1;
          


          但如果你需要更多的參數(shù),括號(hào)是必需的:

          const fun = (a, b) => a + b + 1;
          


          箭頭函數(shù)也可以作為對(duì)象方法出現(xiàn),但是它們的行為與常規(guī)函數(shù)不同。在前一段介紹了 this 關(guān)鍵字,它是對(duì)運(yùn)行函數(shù)的對(duì)象的引用。當(dāng)作為對(duì)象方法調(diào)用時(shí),常規(guī)函數(shù)將 this 指向宿主對(duì)象

          var widget = {
           html: "<div></div>",
           showModal: function() {
           console.log(this.html);
           }
          };
          widget.showModal(); // "<div></div>"
          

          而箭頭函數(shù)中的 this 則指向完全不同的東西:

          var widget = {
           html: "<div></div>",
           showModal: () => console.log(this.html)
          };
          widget.showModal(); // undefined
          

          因此,箭頭函數(shù)不太適合作為對(duì)象方法,但是有一些有趣的用例,在本小冊(cè)中,咱們將了解為什么以及何時(shí)有效使用它們。最后,來看一下 IIFE 箭頭函數(shù):

          (() => {
           console.log("aa");
          })();
          

          令人困惑的語法不是嗎? 接著咱們將進(jìn)入下一章。

          傳遞參數(shù)

          ECMAScript 中所有函數(shù)的參數(shù)都是按值傳遞的。也就是說,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣。基本類型值的傳遞如同基本類型變量的復(fù)制一樣,而引用類型值的傳遞,則如同引用類型變量的復(fù)制一樣。有不少開發(fā)者在這一點(diǎn)上可能會(huì)感到困惑,因?yàn)樵L問變量有按值和按引用兩種方式,而參數(shù)只能按值傳遞。

          在向參數(shù)傳遞基本類型時(shí),被傳遞的值會(huì)被復(fù)制給一個(gè)局部變量(即命名參數(shù),或者用 ECMAScript 的概念來說,就是 arguments 對(duì)象中的一個(gè)元素)。在向參數(shù)傳遞引用類型的值時(shí),會(huì)把這個(gè)值在內(nèi)存中的地址復(fù)制給一個(gè)局部變量,因此這個(gè)局部變量的變化會(huì)反映在函數(shù)的外部。請(qǐng)看下面的例子:

          function addTen(){
           num += 10;
           return num
          }
          var count = 20;
          var result = addTen(count);
          alert(count); // 20 沒有變化
          alert(result); // 30
          

          這里的函數(shù) addTen () 有一個(gè)參數(shù) num ,而參數(shù)實(shí)際上是函數(shù)的局部變量。在調(diào)用這個(gè)函數(shù)時(shí),變量 count 作為參數(shù)被傳遞給函數(shù),這個(gè)變量的值是 20。于是,數(shù)值 20 被復(fù)制給參數(shù) num 以便在 addTen() 中使用。在函數(shù)內(nèi)部,參數(shù) num 的值被加上了 10,但這一變化不會(huì)影響函數(shù)外部的 count 變量。參數(shù)的值也將變成 30,從而反映函數(shù)內(nèi)部的修改。當(dāng)然,使用數(shù)值等基本類型值來說明按值傳遞參數(shù)比較簡單,但如果使用對(duì)象,那問題就不怎么好理解了。再舉一個(gè)例子:

          function setName (obj) {
           obj.name = '前端小智';
          }
          var person = new Object();
          setName(person);
          alert(person.name) // "前端小智"
          

          以上代碼創(chuàng)建一個(gè)對(duì)象,并將其保存在了變量 person 中。然后,這個(gè)變量被傳遞到 setName() 函數(shù)中之后就被復(fù)制給了 obj。在這個(gè)函數(shù)內(nèi)部, obj 和 person引用的是同一個(gè)對(duì)象。于是,當(dāng)在函數(shù)內(nèi)部為 obj 添加 name 屬性后,函數(shù)外部的 person 也將有所反映;因?yàn)閜erson指向的對(duì)象在堆內(nèi)存中只有一個(gè),而且是全局對(duì)象。

          有很多開發(fā)者錯(cuò)誤的認(rèn)為:在局部作用域中修改的對(duì)象會(huì)在全局作用域中反映出來,就說明參數(shù)是按引用傳遞。為了證明對(duì)象是按值傳遞的,我們?cè)倏匆豢聪旅孢@個(gè)經(jīng)過修改的例子:

          function setName(obj) {
           obj.name = '前端小智';
           obj = new Object();
           obj.name = '王大冶'
          }
          var person = new Object();
          setName(person);
          alert(person.name) // '前端小智'
          

          這個(gè)例子與前一個(gè)例子的唯一區(qū)別,就是在 setName() 函數(shù)中添加了兩行代碼:一行代碼為 obj 重新定義了一個(gè)對(duì)象,另一行代碼為該對(duì)象定義了一個(gè)帶有不同值的 name 屬性。在把 person 傳遞給 setName() 后,其 name 屬性被設(shè)置為 ‘前端小智’。然后,又將一個(gè)新對(duì)象賦給變量 obj,同時(shí)將其 name 屬性設(shè)置為 '王大冶'。

          如果 person 是按引用傳遞的,那么 person 就會(huì)自動(dòng)被修改為指向其 name 屬性為 ‘王大冶'的新對(duì)象。但是原始的引用仍然保持不變。實(shí)際上,當(dāng)在函數(shù)內(nèi)部重寫 obj 時(shí),這個(gè)變量引用就是一個(gè)局部對(duì)象了。而這個(gè)局部對(duì)象會(huì)在函數(shù)執(zhí)行完畢后立即被銷毀。

          總結(jié)

          JS 具有七個(gè)稱為 “類型” 的基本構(gòu)建塊,其中 6 個(gè)也稱為基本數(shù)據(jù)類型。Object 本身就是一種類型,也是該語言最重要的實(shí)體。對(duì)象是用于一對(duì)鍵/值的容器,并且可以包含幾乎所有其他 JS 的類型,包括函數(shù)。

          與大多數(shù)其他編程語言一樣,JS 有字符串、數(shù)字、函數(shù)、布爾值和一些稱為 Null 和Undefined 的特殊類型。JS 中有兩種函數(shù):箭頭函數(shù)和常規(guī)函數(shù)。它們都有各自的用法,根據(jù)場景使用它們。

          思考

          • arguments 和 參數(shù) 之間有什么區(qū)別?
          • JS 中有多少個(gè)基本類型
          • 什么是常規(guī)的箭頭函數(shù)
          • 函數(shù)作為對(duì)象方法運(yùn)行時(shí)可以訪問哪些特殊關(guān)鍵字?
          • 在 JS 中聲明變量有多少種方法

          代碼部署后可能存在的BUG沒法實(shí)時(shí)知道,事后為了解決這些BUG,花了大量的時(shí)間進(jìn)行l(wèi)og 調(diào)試,這邊順便給大家推薦一個(gè)好用的BUG監(jiān)控工具Fundebug。

          原文:https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter1.md

          https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter2.md

          作者:valentinogagliardi

          譯者:前端小智

          來源:github

          者:Joanne Lee-(Vivi)
          譯者: 前端小智
          來源:medium

          1.如何理解 JS 中的`this`關(guān)鍵字?

          JS 初學(xué)者總是對(duì) this 關(guān)鍵字感到困惑,因?yàn)榕c其他現(xiàn)代編程語言相比,JS 中的這this關(guān)鍵字有點(diǎn)棘手。 “this” 一般是表示當(dāng)前所在的對(duì)象,但是事情并沒有像它應(yīng)該的那樣發(fā)生。JS中的this關(guān)鍵字由函數(shù)的調(diào)用者決定,誰調(diào)用就this就指向哪個(gè)。如果找不到調(diào)用者,this將指向windows對(duì)象。

          來幾個(gè)粟子

          第一個(gè)例子很簡單。 調(diào)用 test對(duì)象中的 func(),因此func() 中的'this'指向的是 test 對(duì)象,所以打印的 prop 是 test 中的 prop,即 42。

          如果我們直接調(diào)用getFullname函數(shù),第二個(gè)例子將打印出'David Jones',因?yàn)榇藭r(shí) this 找不到調(diào)用者,所以默認(rèn)就為 window 對(duì)象,打印的 fullname 即是全局的。

          2. 由于 `this` 關(guān)鍵字很混亂,如何解決這個(gè)問題

          有很多方法可以解決這個(gè)問題; 但是,無論你選擇哪種解決方案,最重要的是要知道你決定讓 this 指向哪個(gè)對(duì)象。

          一旦你弄清楚了this指向的對(duì)象,你就可以直接將它改成對(duì)象名。 否則,使用bind,call,apply函數(shù)也可以解決問題。

          3.什么是閉包

          當(dāng)我第一次解釋閉包時(shí),我常說函數(shù)中的函數(shù);但是,它沒有正確地描述閉包的確切含義。

          閉包是在另一個(gè)作用域內(nèi)創(chuàng)建一個(gè)封閉的詞法范圍。它通常會(huì)自動(dòng)返回來生成這個(gè)詞法環(huán)境。這個(gè)環(huán)境由創(chuàng)建閉包時(shí)在作用域內(nèi)的任何局部變量組成。它就像一個(gè)微型工廠,用這些原料生產(chǎn)出具有特定功能的產(chǎn)品。

          閉包的另一個(gè)應(yīng)用是創(chuàng)建私有變量和方法。JavaScript不像Java那樣可以很好地支持oop。在JS中沒有明確的方法來創(chuàng)建私有方法,但是閉包可以私有方法。

          4.解釋一下變量的提升

          變量的提升是JavaScript的默認(rèn)行為,這意味著將所有變量聲明移動(dòng)到當(dāng)前作用域的頂部,并且可以在聲明之前使用變量。初始化不會(huì)被提升,提升僅作用于變量的聲明。

          var x = 1
          console.log(x + '——' + y) // 1——undefined
          var y = 2

          5. JavaScript如何處理同步和異步情況

          盡管JavaScript是一種只有一個(gè)調(diào)用堆棧的單線程編程語言,但它也可以使用一個(gè)稱為事件循環(huán)(event loop)的機(jī)制來處理一些異步函數(shù)。從基本級(jí)別了解JavaScript如何工作是理解JS如何處理異步的關(guān)鍵部分。

          如圖所示,調(diào)用堆棧是定位函數(shù)的位置。一旦函數(shù)被調(diào)用,函數(shù)將被推入堆棧。然而,異步函數(shù)不會(huì)立即被推入調(diào)用堆棧,而是會(huì)被推入任務(wù)隊(duì)列(Task Queue),并在調(diào)用堆棧為空后執(zhí)行。將事件從任務(wù)隊(duì)列傳輸?shù)秸{(diào)用堆棧稱為事件循環(huán)

          6. 如何理解事件委托

          在DOM樹上綁定事件監(jiān)聽器并使用JS事件處理程序是處理客戶端事件響應(yīng)的典型方法。 從理論上講,我們可以將監(jiān)聽器附加到HTML中的任何DOM元素,但由于事件委派,這樣做是浪費(fèi)而且沒必要的。

          什么是事件委托?

          這是一種讓父元素上的事件監(jiān)聽器也影響子元素的技巧。 通常,事件傳播(捕獲和冒泡)允許我們實(shí)現(xiàn)事件委托。 冒泡意味著當(dāng)觸發(fā)子元素(目標(biāo))時(shí),也可以逐層觸發(fā)該子元素的父元素,直到它碰到DOM綁定的原始監(jiān)聽器(當(dāng)前目標(biāo))。 捕獲屬性將事件階段轉(zhuǎn)換為捕獲階段,讓事件下移到元素; 因此,觸發(fā)方向與冒泡階段相反。 捕獲的默認(rèn)值為false。

          7. 如何理解高階函數(shù)

          JavaScript中的一切都是對(duì)象,包括函數(shù)。我們可以將變量作為參數(shù)傳遞給函數(shù),函數(shù)也是如此。我們調(diào)用接受和或返回另一個(gè)函數(shù)稱為高階函數(shù)的函數(shù)。

          8. 如何區(qū)分聲明函數(shù)和表達(dá)式函數(shù)

          // 聲明函數(shù)
          function hello() {
           return "HELLO"
          } 
          // 表達(dá)式函數(shù) 
          var h1 = function hello() {
           return "HELLO"
          } 

          兩個(gè)函數(shù)將在不同的時(shí)期定義。在解析期間定義聲明,在運(yùn)行時(shí)定義表達(dá)式;因此,如果我們控制臺(tái)打印 h1,它將顯示HELLO。

          9.解釋原型繼承是如何工作的

          JavaScript不是一種面向?qū)ο蟮挠押镁幊陶Z言,但它仍然使用繼承的思想來實(shí)現(xiàn)依賴關(guān)系,并使用許多內(nèi)置函數(shù)使其靈活使用。了解原型繼承的工作原理將使你很好地理解JavaScript知識(shí),從而避免概念上的誤用。

          最好在大腦中描繪一下JavaScript的整個(gè)機(jī)制,以了解原型繼承。

          JavaScript中有一個(gè)超級(jí)對(duì)象,所有對(duì)象都將從中繼承。 '__ proto__'指向的對(duì)象的Prototype內(nèi)部屬性。 原型(prototype )包含一個(gè)構(gòu)造函數(shù),使對(duì)象能夠從中創(chuàng)建實(shí)例。 __proto__始終存在于對(duì)象中,并且分層指向它所屬的原型,直到null,這稱為原型鏈

          10. 解釋一下嚴(yán)格模式(strict mode)

          嚴(yán)格模式用于標(biāo)準(zhǔn)化正常的JavaScript語義。嚴(yán)格模式可以嵌入到非嚴(yán)格模式中,關(guān)鍵字 ‘use strict’。使用嚴(yán)格模式后的代碼應(yīng)遵循JS嚴(yán)格的語法規(guī)則。例如,分號(hào)在每個(gè)語句聲明之后使用。

          原文:https://medium.com/@jlanne119/10-popular-interview-questions-of-javascript-for-front-end-developers-973c2052892e


          主站蜘蛛池模板: 末成年女A∨片一区二区| 亚洲蜜芽在线精品一区| 日韩精品一区二区三区影院| 人妻体体内射精一区二区| 成人精品一区二区三区不卡免费看 | 人妻互换精品一区二区| 97久久精品一区二区三区| 加勒比无码一区二区三区| 日本亚洲成高清一区二区三区| 久久精品岛国av一区二区无码| 亚洲AV一区二区三区四区| 精品不卡一区中文字幕| 国产精品视频一区二区三区| 亚洲国产精品一区第二页 | 成人无码AV一区二区| 无码人妻精一区二区三区| 国产精品一区二区久久不卡| 久热国产精品视频一区二区三区| 韩国福利影视一区二区三区| 成人精品一区二区三区不卡免费看| 国精品无码A区一区二区| 成人一区二区三区视频在线观看| 韩国福利一区二区三区高清视频| 国产精品熟女视频一区二区| 日本高清一区二区三区| 人妻少妇AV无码一区二区| 精品国产天堂综合一区在线| 精品一区二区三区无码免费视频| 久久亚洲中文字幕精品一区四| 国产亚洲情侣一区二区无| 国产主播一区二区三区在线观看| 日本精品一区二区在线播放| 精品无人区一区二区三区在线| 色欲AV蜜臀一区二区三区| 精品国产亚洲一区二区三区| 亚洲国产成人一区二区三区| 无码人妻一区二区三区免费视频 | 国产在线精品一区二区中文| 亚洲性日韩精品一区二区三区 | 无码午夜人妻一区二区不卡视频| 国产精品揄拍一区二区久久|