和往常一樣,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客戶端解決方案了!
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')
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編碼文本。
常規(guī)操作
import * as jsPDF from 'jspdf'
有些框架,必須像下面這樣
import jsPDF from 'jspdf';
jsPDF的api非常豐富,在這里就不提供相關(guān)地址了,在Github必然找的到,本文重點(diǎn)不在于介紹jsPDF的用法,將部分API截圖展示,通過名稱大致能猜到一些意思,具體用法需要參考官網(wǎng)文檔:
從截圖來看,其文檔特別的詳細(xì),具體到每一個(gè)API在js文件的行數(shù),便于閱讀源代碼,包括參數(shù)以及返回值都非常明確:
官方提供了一個(gè)在線demo,可以直接運(yùn)行代碼,感興趣的可以先嘗試一下:
jsPDF是筆者見過類似產(chǎn)品中較為突出的,幾乎涵蓋了所有PDF相關(guān)操作,非常詳細(xì)的文檔也讓開發(fā)者,輕松上手,在線demo還能快速學(xué)習(xí),如果你的項(xiàng)目對(duì)PDF的操作比較多,不妨嘗試下jsPDF,唯一需要注意的就是解決字體問題,但是上文也提到過解決方案,感興趣的可以進(jìn)行體驗(yàn)!
了保證的可讀性,本文采用意譯而非直譯。
什么是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è)生涯不利。
JS 目前有 7 種基本類型,如下:
除了 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 聲明的變量與在封閉或外部塊中聲明的相同變量名不重疊。例如:
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ù)是最傳統(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ù)很方便,但我建議不要過度使用它們。這是一個(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ù)場景使用它們。
思考
代碼部署后可能存在的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
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 即是全局的。
有很多方法可以解決這個(gè)問題; 但是,無論你選擇哪種解決方案,最重要的是要知道你決定讓 this 指向哪個(gè)對(duì)象。
一旦你弄清楚了this指向的對(duì)象,你就可以直接將它改成對(duì)象名。 否則,使用bind,call,apply函數(shù)也可以解決問題。
當(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)建私有方法,但是閉包可以私有方法。
變量的提升是JavaScript的默認(rèn)行為,這意味著將所有變量聲明移動(dòng)到當(dāng)前作用域的頂部,并且可以在聲明之前使用變量。初始化不會(huì)被提升,提升僅作用于變量的聲明。
var x = 1 console.log(x + '——' + y) // 1——undefined var y = 2
盡管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)。
在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。
JavaScript中的一切都是對(duì)象,包括函數(shù)。我們可以將變量作為參數(shù)傳遞給函數(shù),函數(shù)也是如此。我們調(diào)用接受和或返回另一個(gè)函數(shù)稱為高階函數(shù)的函數(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,這稱為原型鏈。
嚴(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
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。