摘要:所以我們又可以得出一個結論原型的屬性指向構造函數,構造函數又通過屬性指回原型,但是并不是所有函數都具有這個屬性,就沒有這個屬性。
1.原始類型
boolean number string null undefined symbol
原始類型儲存的都是值,是沒有函數可以調用的,undefined.toString() 顯示報錯,
但是"1".toString() // "1" ; 是因為"1"被強制轉換成了string類型,已經不是原始類型而是對象類型了;
用typeOf可以判斷除了null的原始類型,typeOf null // OBJECT
判斷null為object類型,其實這是js的一個bug, JS的最初版使用32位系統,為了性能考慮使用低位儲存變量信息,000開頭表示對象,而null都是0,所以判斷null顯示為對象。
再JS中除了原始類型之外都是對象類型,原始類型儲存的是值,而對象類型儲存的是地址(指針),
const a = [];
我們假設常量a的指針是#001, 那么#001存放了值是[];
const a = []; const b = a; b.push(1);
根據上面所說,我們將常量a的值賦給b,其實是將a的指針傳給了b,即b也變成了#001,
那么當我們改變b的值其實是改變了#001的值,同樣會導致a的值發生變化;
接下來我們看看函數參數是對象的情況來看看
function test(person) { person.age = 26 person = { name: "yyy", age: 30 } return person } const p1 = { name: "wpp", age: 25 } const p2 = test(p1) console.log(p1) // -> ? console.log(p2) // -> ?
答案是什么呢?
我們來分析一下
首先,函數傳參是傳遞對象指針的副本,
到函數內部修改參數的屬性這步,p1的值也被修改了,
但是我們重新為person分配了一個對象時就出現了分歧,
所以最后person擁有了一個新的指針,也就和p1沒有任何關系了,導致最終兩個的值是不一樣的。
typeOf對于原始類型除了null之外都能正確判斷,而對于判斷對象,除了函數都會顯示object,所以我們不能使用typeOf來判斷對象的類型;
如果我們想去判斷一個原始類型我們可以使用instanceof來判斷;其內部機制是通過原型鏈來判斷的
對于原始類型我們直接使用instanceof來判斷是不行的,當然我們還要辦法使用instanceof來判斷原始類型;
class PrimitiveString { static [Symbol.hasInstance](x) { return typeof x === "string" } } console.log("hello world" instanceof PrimitiveString) // true
你可能不知道 Symbol.hasInstance 是什么東西,其實就是一個能讓我們自定義 instanceof 行為的東西,以上代碼等同于 typeof "hello world" === "string",所以結果自然是 true 了。這其實也側面反映了一個問題, instanceof 也不是百分之百可信的。
4.This 如何正確判斷 this?箭頭函數的 this 是什么?誰最后調用了this,this就指向誰
function foo() { console.log(this.a) } var a = 1 foo() const obj = { a: 2, foo: foo } obj.foo() const c = new foo()
我們來分析一下上面的級格場景
直接調用foo() ,this指向windows;
obj.foo obj最后調用foo,this指向obj;
對于new來說this被綁定在了c上面。不會被改變;
接下來我們看看箭頭函數中的this指向情況,
function a() { return () => { return () => { console.log(this) } } } console.log(a()()())
首先箭頭函數其實是沒有 this 的,箭頭函數中的 this 只取決包裹箭頭函數的第一個普通函數的 this。在這個例子中,因為包裹箭頭函數的第一個普通函數是 a,所以此時的 this 是 window。另外對箭頭函數使用 bind 這類函數是無效的。
最后種情況也就是 bind 這些改變上下文的 API 了,對于這些函數來說,this 取決于第一個參數,如果第一個參數為空,那么就是 window。
以上就是 this 的規則了,但是可能會發生多個規則同時出現的情況,這時候不同的規則之間會根據優先級最高的來決定 this 最終指向哪里。
首先,new 的方式優先級最高,接下來是 bind 這些函數,然后是 obj.foo() 這種調用方式,最后是 foo 這種調用方式,同時,箭頭函數的 this 一旦被綁定,就不會再被任何方式所改變。
5.== vs === == 和 === 有什么區別?對于 == 來說,如果對比雙方的類型不一樣的話,就會進行類型轉換
對于 === 來說就簡單多了,就是判斷兩者類型和值是否相同
簡單來講就是函數A內有函數B,并且函數B可以訪問到函數A中的變量,函數B就叫做閉包。
JS中閉包存在的意義是什么呢?
是為了讓我們間接訪問到函數內部的變量,
一個面試經典問題
for (var i = 1; i <= 5; i++) { setTimeout(function timer() { console.log(i) }, i * 1000) }
首先因為 setTimeout 是個異步函數,所以會先把循環全部執行完畢,這時候 i 就是 6 了,所以會輸出一堆 6。
第一種方式
for (var i = 1; i <= 5; i++) { ;(function(j) { setTimeout(function timer() { console.log(j) }, j * 1000) })(i) }
第二種方式
for (let i = 1; i <= 5; i++) { setTimeout(function timer() { console.log(i) }, i * 1000) }
直接使用let來代替var 也能解決這個問題
7.深拷貝和淺拷貝 什么是淺拷貝?如何實現淺拷貝?什么是深拷貝?如何實現深拷貝?我們了解了對象類型在賦值的過程中其實是復制了地址,從而會導致改變了一方其他也都被改變的情況。通常在開發中我們不希望出現這樣的問題,我們可以使用淺拷貝來解決這個情況
淺拷貝首先可以通過 Object.assign 來解決這個問題,很多人認為這個函數是用來深拷貝的。其實并不是,Object.assign 只會拷貝所有的屬性值到新的對象中,如果屬性值是對象的話,拷貝的是地址,所以并不是深拷貝。
let a = { age: 1 } let b = Object.assign({}, a) a.age = 2 console.log(b.age) // 1
我們還可以使用...運算符來解決這個問題
let a = { age: 1 } let b = { ...a } a.age = 2 console.log(b.age) // 1
通常淺拷貝就能解決大部分問題了,但是當我們遇到如下情況就可能需要使用到深拷貝了
let a = { age: 1, jobs: { first: "FE" } } let b = { ...a } a.jobs.first = "native" console.log(b.jobs.first) // native
淺拷貝只解決了第一層的問題,如果接下去的值中還有對象的話,那么就又回到最開始的話題了,兩者享有相同的地址。要解決這個問題,我們就得使用深拷貝了。
深拷貝這個問題通常可以通過 JSON.parse(JSON.stringify(object)) 來解決。
但是這個方法也有局限性
會忽略undefined
會忽略symbol
不能序列化函數
不能解決循環引用的問題
但是大部分情況這個方法都可以適用
8.原型 如何理解原型?如何理解原型鏈?每個 JS 對象都有 proto 屬性,這個屬性指向了原型。這個屬性在現在來說已經不推薦直接去使用它了,這只是瀏覽器在早期為了讓我們訪問到內部屬性 [[prototype]] 來實現的一個東西。
好像還是沒有弄明白什么是原型,接下來讓我們再看看 proto 里面有什么吧。
看到這里我們會發現原型也是對象,并且這個對象中包含了很多函數,所以我們可以得出一個結論:對于 obj 來說,可以通過 proto 找到一個原型對象,在該對象中定義了很多函數讓我們來使用。
在上面的圖中我們還可以發現一個 constructor 屬性,也就是構造函數
打開 constructor 屬性我們又可以發現其中還有一個 prototype 屬性,并且這個屬性對應的值和先前我們在 proto 中看到的一模一樣。所以我們又可以得出一個結論:原型的 constructor 屬性指向構造函數,構造函數又通過 prototype 屬性指回原型,但是并不是所有函數都具有這個屬性,Function.prototype.bind() 就沒有這個屬性。
https://juejin.im/post/5c4fdb...
原型的詳細介紹
再JS中類型轉換只分三種情況:
轉換成布爾值,轉換成數字,轉換成字符串;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102203.html
摘要:搭建更新代碼的腳手架加載化使用基于的緩存機制,就需要一個腳手架來管理資源文件的讀取和寫入,不難看出微信使用的是自己開發的腳手架,閱讀其源碼代價較大,暫不分析。 黑科技:LocalStorage 緩存機制 事情的起因是我的同事金果問我:- 你知道微信公眾號文章的渲染方式嗎? 對此,我的反應是:- 啊? 金果繼續問:- 控制臺的 Network 里沒有發生任何請求,文章里的內容是怎么來的?...
摘要:參考資料下文是關于的方法的第一個參數的學習。因此,會展開為和。獲取目錄下所有文件名長度為字符的文件。匹配該路徑段中在指定范圍內的一個字符。匹配完全且精確地匹配,且不可組合不符合任何模型之一的字符。可通過在設置,讓將視為普通字符。 參考資料:https://github.com/isaacs/nod... 下文是關于 Gulp 的 gulp.src(globs[, options]) 方...
摘要:示例代碼插入斷點方法在需要設置斷點的地方插入關鍵字,程序會在這里暫停運行。只需要在命令模式輸入,按回車便可以進入環境。 1 示例代碼 app.js var express = require(express); var app = express(); var req_times = 0; app.all(/*, function(req, res){ req_times...
摘要:,中文可發音為烏米,是一個可插拔的企業級應用框架。以路由為基礎的,支持類的約定式路由,以及各種進階的路由功能,并以此進行功能擴展,比如支持路由級的按需加載。全局存于目錄,所有頁面都可引用頁面不能被其他頁面所引用。 umi,中文可發音為烏米,是一個可插拔的企業級 react 應用框架。umi 以路由為基礎的,支持類 next.js 的約定式路由,以及各種進階的路由功能,并以此進行功能擴展...
摘要:前言的單文件組件看著十分誘人,必須要上心有不甘,搗騰一番就有了這個不需要也能輕松愉快的用上單文件組件主要針對輕度使用場景,快速應用大型應用,專業前端,工程化前端還是更好快速入門單例組件是一種特殊的全局組件,和插件有點相似,只不過插件可以有更 前言 Vue 的單文件組件(Single File Component)看著十分誘人,But 必須要上 webpack心有不甘,搗騰一番就有了這個...
閱讀 1671·2021-09-26 10:00
閱讀 2935·2021-09-06 15:00
閱讀 3538·2021-09-04 16:40
閱讀 2298·2019-08-30 15:44
閱讀 715·2019-08-30 10:59
閱讀 1883·2019-08-29 18:34
閱讀 3616·2019-08-29 15:42
閱讀 2292·2019-08-29 15:36