js類(lèi)型判斷內(nèi)部實(shí)現(xiàn)原理示例詳解
typeof
typeof 操作符唯一的目的就是檢查數(shù)據(jù)類(lèi)型
| 類(lèi)型 | typeof 結(jié)果 | |
|---|---|---|
| 基本類(lèi)型 | undefined | undefined |
| Boolean | boolean | |
| Number | number | |
| String | string | |
| Symbol | symbol | |
| BigInt | bigint | |
| null | object | |
| 引用類(lèi)型 | Object(Object, Array, Map, Set, Regexp, Date 等) | object |
| Function | function |
你會(huì)發(fā)現(xiàn)用typeof來(lái)判斷引用類(lèi)型時(shí), 都會(huì)返回 'object'. 為此, 引入了 instanceof
instanceof 運(yùn)算符用于檢測(cè)構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在某個(gè)實(shí)例對(duì)象的原型鏈上。
var arr = [];
arr instanceof Array; // true
typeof arr; // "object"
function A() {}
function B() {}
// Javascript 繼承
B.prototype = new A();
var b = new B();
b instanceof A; // true
b instanceof B; // trueinstanceof 的內(nèi)部實(shí)現(xiàn)原理
- 思路:
利用 原型和原型鏈, 每一個(gè)函數(shù)都有一個(gè)顯式的 prototype, 每一個(gè)對(duì)象都有一個(gè)隱式原型 **proto**, 當(dāng)我們對(duì)象的原型鏈中存在構(gòu)造函數(shù)的顯式原型 prototype時(shí), 我們就可以確定它們之間存在關(guān)系;
function myInstanceOf(constructor, instance) {
let prototype = constructor.prototype;
let proto = instance.__proto__;
while (true) {
// 說(shuō)明道原型鏈訂單, 還未找到, 返回 false
if (proto === null) {
return false;
}
if (proto === prototype) {
return true;
}
// 繼續(xù)向 proto 的原型鏈上遍歷
proto = Object.getPrototypeOf(proto);
}
}Object.prototype.toString()
- toString() 方法返回一個(gè)表示該對(duì)象的字符串。該方法旨在重寫(xiě)(自定義)派生類(lèi)對(duì)象的類(lèi)型轉(zhuǎn)換的邏輯。
- valueOf() 方法返回對(duì)象的原始值表示
該方法由 字符串轉(zhuǎn)換優(yōu)先調(diào)用, 但是 數(shù)字的強(qiáng)制轉(zhuǎn)換和原始值的強(qiáng)制轉(zhuǎn)換 會(huì)優(yōu)先調(diào)用 valueOf, 因?yàn)榛镜?nbsp;valueOf() 方法返回一個(gè)對(duì)象,toString() 方法通常在結(jié)束時(shí)調(diào)用
默認(rèn)情況下(不重寫(xiě) toString方法), 任何一個(gè)對(duì)象調(diào)用 Object原生的 toString方法, 都會(huì)返回一個(gè) [object type], 其中 type是對(duì)象的類(lèi)型
let a = {};
a; // {}
a.toString(); // "[object Object]"[[class]]
每個(gè) 實(shí)例 都有一個(gè) [[Class]] 屬性,這個(gè)屬性中就指定了上述字符串中的 type 。 [[Class]] 不能直接地被訪問(wèn),但通??梢酝ㄟ^(guò) Object.prototype.toString.call(..) 方法調(diào)用來(lái)展示。
// Boolean 類(lèi)型,tag 為 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"
// Number 類(lèi)型,tag 為 "Number"
Object.prototype.toString.call(10); // => "[object Boolean]"
// String 類(lèi)型,tag 為 "String"
Object.prototype.toString.call("1312312"); // => "[object String]"
// Array 類(lèi)型,tag 為 "String"
Object.prototype.toString.call([]); // => "[object Array]"
// Function 類(lèi)型, tag 為 "Function"
Object.prototype.toString.call(function () {}); // => "[object Function]"
// Error 類(lèi)型(包含子類(lèi)型),tag 為 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"
// RegExp 類(lèi)型,tag 為 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"
// Date 類(lèi)型,tag 為 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"
// 其他類(lèi)型,tag 為 "Object"
Object.prototype.toString.call(new (class {})()); // => "[object Object]"所以可以通過(guò)這個(gè)方法來(lái)判斷每個(gè)對(duì)象的類(lèi)型
function generator(type){
return function(value){
return Object.prototype.toString.call(value) === "[object "+ type +"]"
}
}
let isFunction = generator('Function')
let isArray = generator('Array');
let isDate = generator('Date');
let isRegExp = generator('RegExp');
isArray([])); // true
isDate(new Date()); // true
isRegExp(/\w/); // true
isFunction(function(){}); //true以下是一道簡(jiǎn)單的面試題
+[1 + [2] + 3] + [1 + 2 + true - false] + [[3 - false + "1"]]; // 拆分一下 let a = +[1 + [2] + 3]; // [2]會(huì)首先進(jìn)行轉(zhuǎn)換 [2].valueOf, 結(jié)果不是基本類(lèi)型, [2]在調(diào)用toString(), 返回'2', 最后 1 + '2' + 3, 1,3進(jìn)行隱式轉(zhuǎn)換, +'123' ==> 123 let b = [1 + 2 + true - false]; // [3+true-false], true, false會(huì)進(jìn)行轉(zhuǎn)換, true=>1, false=>0, 最后1-0==>[1+3]==>[4]==>[4].valueOf().toString()==>'4' let c = [[3 - false + "1"]]; // 先轉(zhuǎn)換數(shù)組里面的一層, [3-0+'1']==>['31'], 結(jié)果: [['31']]==>[['31']].valueOf().toString()==>'31' // 最后 a+b+c // 123+'4'+'31'==>123431
面試題目, 如何同時(shí)讓等式成立, a===1&&a===2&&a===3
思路:
重寫(xiě) a 的 valueOf 方法
let a = {
value: [3, 2, 1],
valueOf: function () {
return this.value.pop();
},
};總結(jié)
- 當(dāng)一側(cè)為 String 類(lèi)型,被識(shí)別為字符串拼接,并會(huì)優(yōu)先將另一側(cè)轉(zhuǎn)換為字符串類(lèi)型。
- 當(dāng)一側(cè)為 Number 類(lèi)型,另一側(cè)為原始類(lèi)型,則將原始類(lèi)型轉(zhuǎn)換為 Number 類(lèi)型。
- 當(dāng)一側(cè)為 Number 類(lèi)型,另一側(cè)為引用類(lèi)型,將引用類(lèi)型和 Number 類(lèi)型轉(zhuǎn)換成字符串后拼接。
- 只有 null undefined '' NaN 0 false 這幾個(gè)是 false,其他的情況都是 true,比如 {} , []。
以上就是js類(lèi)型判斷內(nèi)部實(shí)現(xiàn)原理示例詳解的詳細(xì)內(nèi)容,更多關(guān)于js類(lèi)型判斷內(nèi)部原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript?sort方法實(shí)現(xiàn)數(shù)組升序降序
這篇文章主要為大家介紹了JavaScript?sort方法實(shí)現(xiàn)數(shù)組升序降序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07
在JavaScript實(shí)例對(duì)象中改寫(xiě)原型方法詳情
這篇文章主要介紹了在JavaScript實(shí)例對(duì)象中改寫(xiě)原型方法的一下相關(guān)資料,需要的效果版可以參考一下文章詳細(xì)內(nèi)容,希望對(duì)你有所幫助2021-10-10
AngularJS 表達(dá)式詳細(xì)講解及實(shí)例代碼
本文主要介紹AngularJS 表達(dá)式,這里對(duì)AngularJS 表達(dá)式詳細(xì)介紹和實(shí)例代碼,有需要的小伙伴可以參考下2016-07-07
JavaScript原型鏈中函數(shù)和對(duì)象的理解
這篇文章主要為大家介紹了JavaScript原型鏈中函數(shù)和對(duì)象的理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
fabric.js圖層功能獨(dú)立顯隱?添加?刪除?預(yù)覽實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了fabric.js圖層功能獨(dú)立顯隱?添加?刪除?預(yù)覽實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
微信小程序 跳轉(zhuǎn)傳遞數(shù)據(jù)的實(shí)例
這篇文章主要介紹了微信小程序 跳轉(zhuǎn)傳遞數(shù)據(jù)的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-07-07

