在线不卡日本ⅴ一区v二区_精品一区二区中文字幕_天堂v在线视频_亚洲五月天婷婷中文网站

  • <menu id="lky3g"></menu>
  • <style id="lky3g"></style>
    <pre id="lky3g"><tt id="lky3g"></tt></pre>

    JavaScript中的數(shù)據(jù)類型判斷

    typeof

    typeof 操作符返回一個字符串,表示未經(jīng)計算的操作數(shù)的類型。

    語法

    typeof 運算符后接操作數(shù):

    typeof operand

    typeof(operand)

    參數(shù)

    operand 一個表示對象或原始值的表達式,其類型將被返回。

    描述

    下面總結(jié)了 typeof 可能的返回值。有關類型和原始值的更多信息,可查看 JavaScript 數(shù)據(jù)結(jié)構(gòu) 頁面。

    類型

    結(jié)果

    Undefined

    “undefined”

    Null

    “object” (見下文)

    Boolean

    “boolean”

    Number

    “number”

    BigInt (ECMAScript 2020 新增)

    “bigint”

    String

    “string”

    Symbol (ECMAScript 2015 新增)

    “symbol”

    宿主對象(由 JS 環(huán)境提供)

    取決于具體實現(xiàn)

    Function 對象 (按照 ECMA-262 規(guī)范實現(xiàn) [[Call]])

    “function”

    其他任何對象

    “object”

    原始值

    除對象類型(object)以外的其它任何類型定義的不可變的值(值本身無法被改變)。例如(與 C 語言不同),JavaScript 中字符串是不可變的(譯注:如,JavaScript 中對字符串的操作一定返回了一個新字符串,原始字符串并沒有被改變)。我們稱這些類型的值為“原始值”。

    特性

    1、typeof 總是返回一個字符串。

    2、typeof 能正確判斷原始值的類型,null 除外;引用類型數(shù)據(jù)能正確判斷 Function、函數(shù)的類型,其他的都會返回 ‘object’。

    示例

    // 數(shù)值console.log(typeof 37 === ‘number’) // trueconsole.log(typeof 3.14 === ‘number’) // trueconsole.log(typeof (42) === ‘number’) // trueconsole.log(typeof Math.LN2 === ‘number’) // trueconsole.log(typeof Infinity === ‘number’) // trueconsole.log(typeof NaN === ‘number’) // true 盡管它是 “Not-A-Number” (非數(shù)值) 的縮寫console.log(typeof Number(1) === ‘number’) // true Number 會嘗試把參數(shù)解析成數(shù)值console.log(typeof 42n === ‘bigint’) // true// 字符串console.log(typeof ” === ‘string’) // trueconsole.log(typeof ‘bla’ === ‘string’) // trueconsole.log(typeof `template literal` === ‘string’) // trueconsole.log(typeof ‘1’ === ‘string’) // true 注意內(nèi)容為數(shù)字的字符串仍是字符串console.log(typeof (typeof 1) === ‘string’) // true typeof 總是返回一個字符串console.log(typeof String(1) === ‘string’) // true String 將任意值轉(zhuǎn)換為字符串,比 toString 更安全// 布爾值console.log(typeof true === ‘boolean’) // trueconsole.log(typeof false === ‘boolean’) // trueconsole.log(typeof Boolean(1) === ‘boolean’) // Boolean() 會基于參數(shù)是真值還是虛值進行轉(zhuǎn)換console.log(typeof !!(1) === ‘boolean’) // true 兩次調(diào)用 ! (邏輯非) 操作符相當于 Boolean()// Symbolsconsole.log(typeof Symbol() === ‘symbol’) // trueconsole.log(typeof Symbol(‘foo’) === ‘symbol’) // trueconsole.log(typeof Symbol.iterator === ‘symbol’) // true// Undefinedconsole.log(typeof undefined === ‘undefined’) // trueconsole.log(typeof declaredButUndefinedVariable === ‘undefined’) // trueconsole.log(typeof undeclaredVariable === ‘undefined’) // true// 對象console.log(typeof { a: 1 } === ‘object’) // true// 使用 Array.isArray 或者 Object.prototype.toString.call// 區(qū)分數(shù)組和普通對象console.log(typeof [1, 2, 4] === ‘object’) // trueconsole.log(typeof new Date() === ‘object’) // trueconsole.log(typeof /regex/ === ‘object’) // true 歷史結(jié)果請參閱正則表達式部分// 使用 new 操作符// 除 Function 外的所有構(gòu)造函數(shù)的類型都是 ‘object’var func = new Function()console.log(typeof func) // 返回 ‘function’var A = function() {}var b = new A()console.log(typeof b) // 返回 ‘object’// 下面的例子令人迷惑,非常危險,沒有用處。避免使用它們。console.log(typeof new Boolean(true) === ‘object’) // trueconsole.log(typeof new Number(1) === ‘object’) // trueconsole.log(typeof new String(‘abc’) === ‘object’) // true// 函數(shù)console.log(typeof function () { } === ‘function’) // trueconsole.log(typeof class C { } === ‘function’) // trueconsole.log(typeof Math.sin === ‘function’) // true// Null// JavaScript 誕生以來便如此console.log(typeof null === ‘object’) // true

    在 JavaScript 最初的實現(xiàn)中,JavaScript 中的值是由一個表示類型的標簽和實際數(shù)據(jù)值表示的。對象的類型標簽是 0。由于 null 代表的是空指針(大多數(shù)平臺下值為 0x00),因此,null 的類型標簽是 0,typeof null 也因此返回 “object”。(參考來源)

    console.log(typeof 0); // numberconsole.log(typeof BigInt(Number.MAX_SAFE_INTEGER)); // bigintconsole.log(typeof ‘0’); // stringconsole.log(typeof true); // booleanconsole.log(typeof undefined); // undefinedconsole.log(typeof function () { }); // functionconsole.log(typeof Symbol); // functionconsole.log(typeof Symbol()); // symbolconsole.log(typeof Date); // functionconsole.log(typeof Date()); // stringconsole.log(typeof new Date); // objectconsole.log(typeof new Date()); // objectconsole.log(typeof RegExp); // functionconsole.log(typeof RegExp()); // objectconsole.log(typeof new RegExp); // objectconsole.log(typeof new RegExp()); // objectconsole.log(typeof []); // objectconsole.log(typeof {}); // objectconsole.log(typeof null); // object

    如果我們想判斷一個對象的正確類型,可以考慮使用 instanceof,因為內(nèi)部機制是通過 判斷實例對象的 __proto__ 和生成該實例的構(gòu)造函數(shù)的 prototype 是不是引用的同一個地址(也就是原型鏈的方式)來判斷的。

    錯誤

    在 ECMAScript 2015 之前,typeof 總能保證對任何所給的操作數(shù)返回一個字符串。即便是沒有聲明的標識符,typeof 也能返回 ‘undefined’。使用 typeof 永遠不會拋出錯誤。

    但在加入了塊級作用域的 let 和 const 之后,在其被聲明之前對塊中的 let 和 const 變量使用 typeof 會拋出一個 ReferenceError。塊作用域變量在塊的頭部處于“暫存死區(qū)”,直至其被初始化,在這期間,訪問變量將會引發(fā)錯誤。

    typeof undeclaredVariable === ‘undefined’;typeof newLetVariable; // ReferenceErrortypeof newConstVariable; // ReferenceErrortypeof newClass; // ReferenceErrorlet newLetVariable;const newConstVariable = ‘hello’;class newClass{};

    instanceof

    instanceof 運算符用于檢測構(gòu)造函數(shù) prototype 屬性是否出現(xiàn)在某個實例對象的原型鏈上??梢杂脕砼袛喽紝儆?Object 類型和一些特殊情況的對象,如:數(shù)組和對象,但不能用于基礎數(shù)據(jù)類型

    語法

    object instanceof constructor

    參數(shù)

    object 某個實例對象

    constructor 某個構(gòu)造函數(shù)

    描述

    instanceof 運算符用來檢測 constructor.prototype 是否存在于參數(shù) object 的原型鏈上。

    示例

    B instanceof A:判斷 B 是否為 A 的實例,可以用于繼承關系中

    function Car(make, model, year) { this.make = make; this.model = model; this.year = year;}const auto = new Car(‘Honda’, ‘Accord’, 1998);console.log(auto instanceof Car);// expected output: trueconsole.log(auto instanceof Object);// expected output: true// 定義構(gòu)造函數(shù)function C(){}function D(){}var o = new C();o instanceof C; // true,因為 Object.getPrototypeOf(o) === C.prototypeo instanceof D; // false,因為 D.prototype 不在 o 的原型鏈上o instanceof Object; // true,因為 Object.prototype.isPrototypeOf(o) 返回 trueC.prototype instanceof Object // true,同上C.prototype = {};var o2 = new C();o2 instanceof C; // trueo instanceof C; // false,C.prototype 指向了一個空對象,這個空對象不在 o 的原型鏈上.D.prototype = new C(); // 繼承var o3 = new D();o3 instanceof D; // trueo3 instanceof C; // true 因為 C.prototype 現(xiàn)在在 o3 的原型鏈上

    需要注意的是,如果表達式 obj instanceof Foo 返回 true,則并不意味著該表達式會永遠返回 true,因為 Foo.prototype 屬性的值有可能會改變,改變之后的值很有可能不存在于 obj 的原型鏈上,這時原表達式的值就會成為 false。另外一種情況下,原表達式的值也會改變,就是改變對象 obj 的原型鏈的情況,雖然在目前的ES規(guī)范中,我們只能讀取對象的原型而不能改變它,但借助于非標準的 __proto__ 偽屬性,是可以實現(xiàn)的。比如執(zhí)行 obj.__proto__ = {} 之后,obj instanceof Foo 就會返回 false 了。

    A 是 B 的父對象,c 是 B 的實例,c instanceof A 與 c instanceof B 結(jié)果均為 true。

    function A() { }function B() { }B.prototype = new A()const c = new B()console.log(c instanceof B); // trueconsole.log(c instanceof A); // trueconsole.log(A instanceof B); // falseconsole.log(B instanceof A); // falseconsole.log(B.__proto__ === A.prototype); // falseconsole.log(B.prototype.__proto__ === A.prototype); // trueconsole.log(c instanceof Object); // true c 屬于console.log(B instanceof Object); // trueconsole.log(A instanceof Object); // true

    演示 String 對象和 Date 對象都屬于 Object 類型和一些特殊情況

    下面的代碼使用了 instanceof 來證明:String 和 Date 對象同時也屬于Object 類型(他們是由 Object 類派生出來的)。

    但是,使用對象文字符號創(chuàng)建的對象在這里是一個例外:雖然原型未定義,但 instanceof Object 返回 true。

    var simpleStr = “This is a simple string”;var myString = new String();var newStr = new String(“String created with constructor”);var myDate = new Date();var myObj = {};var myNonObj = Object.create(null);console.log(simpleStr instanceof String) // 返回 false, 非對象實例,因此返回 falseconsole.log(myString instanceof String) // 返回 trueconsole.log(newStr instanceof String) // 返回 trueconsole.log(myString instanceof Object) // 返回 trueconsole.log(myObj instanceof Object) // 返回 true, 盡管原型沒有定義console.log(({}) instanceof Object) // 返回 true, 同上console.log(myNonObj instanceof Object) // 返回 false, 一種創(chuàng)建非 Object 實例的對象的方法console.log(myString instanceof Date) // 返回 falseconsole.log(myDate instanceof Date) // 返回 trueconsole.log(myDate instanceof Object) // 返回 trueconsole.log(myDate instanceof String) // 返回 false

    Object.prototype.toString.call(object)/Object.prototype.toString.apply(object)

    toString.call() 或 toString.apply() 方法幾乎可以精準判斷各類數(shù)據(jù)的類型。

    console.log(Object.prototype.toString.call(“kevin”)) // [object String]console.log(Object.prototype.toString.call(18)) // [object Number]console.log(Object.prototype.toString.call(true)) // [object Boolean]console.log(Object.prototype.toString.call(undefined)) // [object Undefined]console.log(Object.prototype.toString.call(null)) // [object Null]console.log(Object.prototype.toString.call(NaN)) // [object Number]console.log(Object.prototype.toString.call({ name: “kevin” })) // [object Object]console.log(Object.prototype.toString.call(function () { })) // [object Function]console.log(Object.prototype.toString.call([])) // [object Array]console.log(Object.prototype.toString.call(new Date)) // [object Date]console.log(Object.prototype.toString.call(/d/)) // [object RegExp]console.log(Object.prototype.toString.call(Math)) // [object Math]function Person() { }console.log(Object.prototype.toString.call(new Person)) // [object Object]var o = { [Symbol.toStringTag]: “A” }console.log(Object.prototype.toString.call(o)) // [object A]console.log(window.toString()) // “[object Window]”console.log(Object.prototype.toString.call(window)) // “[object Window]”console.log(Object.prototype.toString.call(Symbol())); // “[object Symbol]”// 封裝function getTypeof(data) { let dataType = Object.prototype.toString.call(data); return dataType.slice(8, -1)}console.log(getTypeof(18)) // Numberconsole.log(getTypeof(“kevin”)) // Stringconsole.log(getTypeof(new Date)) // Dateconsole.log(getTypeof([])) // Arrayconsole.log(getTypeof({})) // Objectfunction Person() { }console.log(getTypeof(new Person)) // Objectconsole.log(getTypeof(new Person())) // Object

    語法

    obj.toString()

    返回值

    一個表示該對象的字符串

    描述

    每個對象都有一個 toString() 方法,當該對象被表示為一個文本值時,或者一個對象以預期的字符串方式引用時自動調(diào)用。默認情況下,toString() 方法被每個 Object 對象繼承。如果此方法在自定義對象中未被覆蓋,toString() 返回 “[object type]”,其中 type 是對象的類型。以下代碼說明了這一點:

    var o = new Object();console.log(o.toString()); // [object Object]

    備注:如 ECMAScript 5 和隨后的 Errata 中所定義,從 JavaScript 1.8.5 開始,toString() 調(diào)用 null 返回[object Null],undefined 返回 [object Undefined]。請參閱下面的使用toString()檢測對象類型。

    示例

    覆蓋默認的 toString 方法

    可以自定義一個方法,來取代默認的 toString() 方法。該 toString() 方法不能傳入?yún)?shù),并且必須返回一個字符串。自定義的 toString() 方法可以是任何我們需要的值,但如果它附帶有關對象的信息,它將變得非常有用。

    以下代碼定義了 Dog 對象類型,并創(chuàng)建了一個 Dog 類型的 theDog 對象:

    function Dog(name,breed,color,sex) { this.name = name; this.breed = breed; this.color = color; this.sex = sex;}var theDog = new Dog(“Gabby”, “Lab”, “chocolate”, “female”);// 如果當前的對象調(diào)用了 toString() 方法,它將會返回從 Object繼承而來的 toString() 方法的返回默認值:console.log(theDog.toString()); // 返回 [object Object]// 下面的代碼中定義了一個叫做 dogToString() 的方法來覆蓋默認的 toString() 方法。// 這個方法生成一個 “property = value;” 形式的字符串,該字符串包含了當前對象的 name、breed、color 和 sex 的值。Dog.prototype.toString = function dogToString() { var ret = “Dog ” + this.name + ” is a ” + this.sex + ” ” + this.color + ” ” + this.breed; return ret;}// 也可以這樣寫Dog.prototype.toString = function dogToString() { return `Dog ${this.name} is a ${this.sex} ${this.color} ${this.breed}`;}// 使用上述代碼,任何時候在字符串上下文中使用 theDog.toString() 時,// JavaScript 都會自動調(diào)用 dogToString() 方法(dogToString() 可以是一個匿名函數(shù)),并且返回以下字符串:// “Dog Gabby is a female chocolate Lab”console.log(theDog.toString()); // 返回 “Dog Gabby is a female chocolate Lab”// 也可以這樣寫Dog.prototype.toString = function dogToString() { return ‘[object Dog]’;}Dog.prototype[Symbol.toStringTag] = ‘Dog’// 也可以這樣寫theDog[Symbol.toStringTag] = ‘Dog’console.log(theDog.toString()); // 返回 [object Dog]console.log(Dog.prototype.toString()); // 返回 [object Dog]console.log(Dog.prototype.toString.call(theDog)); // 返回 [object Dog]console.log(Object.prototype.toString.call(theDog)); // 返回 [object Object]

    使用 toString() 檢測對象

    可以通過 toString() 來獲取每個對象的類型。為了每個對象都能通過 Object.prototype.toString() 來檢測,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式來調(diào)用,傳遞要檢查的對象作為第一個參數(shù),稱為 thisArg。

    var toString = Object.prototype.toString;toString.call(new Date); // [object Date]toString.call(new String); // [object String]toString.call(Math); // [object Math]//Since JavaScript 1.8.5toString.call(undefined); // [object Undefined]toString.call(null); // [object Null]

    檢測原理

    Object.prototype.toString.call(obj) 類型檢測的原理是什么?首先我們來看一下 toString() 方法:

    var num = 1console.log(num.toString()) // ‘1’var str = ‘kevin’console.log(str.toString()) // ‘kevin’var bool = falseconsole.log(bool.toString()) // ‘false’var arr = [1, 2, 3]console.log(arr.toString()) // ‘1,2,3’var obj = { name: ‘kevin’ }console.log(obj.toString()) // ‘[object Object]’var fn = function(){}console.log(fn.toString()) // ‘function(){}’console.log(JSON.toString()) // ‘[object JSON]’console.log(Atomics.toString()) // ‘[object Atomics]’console.log(null.toString()) // Cannot read property ‘toString’ of nullconsole.log(undefined.toString() // Cannot read property ‘toString’ of undefinedconsole.log(window.toString()) // ‘[object Window]’

    從以上示例可以知道 toString 是將數(shù)據(jù)轉(zhuǎn)換為字符串(null 和 undefined 除外),并且各種類型的數(shù)據(jù)轉(zhuǎn)換為字符串的方式又不一樣。即若參數(shù)不為 null 或 undefined,則將參數(shù)轉(zhuǎn)為對象,再作判斷。對于原始類型,轉(zhuǎn)為對象的方法即裝箱。

    轉(zhuǎn)為對象后,取得該對象的 [Symbol.toStringTag] 屬性值(可能會遍歷原型鏈)作為 tag,如無該屬性,或該屬性值不為字符串類型,則依下表取得 tag,然后返回 “[object ” + tag + “]” 形式的字符串。

    新標準引入了 [Symbol.toStringTag] 屬性,是為了把此方法接口化,用于規(guī)范新引入的對象對此方法的調(diào)用。但對于“老舊”的對象,就只能直接輸出值,以保證兼容性。

    // 1. 三個容器對象。這類對象用作命名空間,用于存儲同一類方法。JSON[Symbol.toStringTag]; // => “JSON”Math[Symbol.toStringTag]; // => “Math”Atomics[Symbol.toStringTag]; // => “Atomic”// 這三個對象的 toString() 都沒有重寫,直接調(diào)用 toString() 方法也可以得到相同的結(jié)果。JSON.toString(); // => “[object JSON]”Math.toString(); // => “[object Math]”Atomics.toString(); // => “[object Atomics]”// 2. 兩個新引入的類型 BigInt 和 Symbol。BigInt.prototype[Symbol.toStringTag]; // => “BigInt”Symbol.prototype[Symbol.toStringTag]; // => “Symbol”// 3. 四個集合(Collection)對象。Set.prototype[Symbol.toStringTag]; // => “Set”Map.prototype[Symbol.toStringTag]; // => “Map”WeakSet.prototype[Symbol.toStringTag]; // => “WeakSet”WeakMap.prototype[Symbol.toStringTag]; // => “WeakMap”// 4. 在不同的實現(xiàn)中,有些第三方對象也部署了此屬性。// 比如在瀏覽器中:Window.prototype[Symbol.toStringTag]; // => “Window”HTMLElement.prototype[Symbol.toStringTag]; // => “HTMLElement”Blob.prototype[Symbol.toStringTag]; // => “Blob”// 5. 模塊命名空間對象(Module Namespace Object)。// 新引入的模塊命名空間對象(Module Namespace Object)也是部署了此屬性的。import * as module from “./export.js”;module[Symbol.toStringTag]; // => “Moduel”// 6. 在 Node.js 中global[Symbol.toStringTag]; // => “global”

    我們再來看一下 Object 以及其原型上的 toString 方法:

    Object.toString(); // “function Object() { [native code] }”Object.prototype.toString(); // “[object Object]”var o = new Object();console.log(o.toString()); // 返回 [object Object]console.log(o.__proto__.toString()); // 返回 [object Object]console.log(o.__proto__.toString === Object.prototype.toString); // true

    我們可以看出 Object 和它的原型鏈上各自有一個 toString 方法,Object 輸出的是其函數(shù)體 “function Object() { [native code] }”,而 Object 原型上輸出的是其類型 “[object Object]”。

    數(shù)據(jù)類型

    例子

    輸出

    字符串

    “foo”.toString()

    “foo”

    數(shù)字

    1.toString()

    Uncaught SyntaxError: Invalid or unexpected token

    布爾值

    true.toString()

    “true”

    undefined

    undefined.toString()

    Uncaught TypeError: Cannot read property ‘toString’ of undefined

    null

    null.toString()

    Uncaught TypeError: Cannot read property ‘toString’ of null

    String

    String.toString()

    “function String() {[native code]}”

    Number

    Number.toString()

    “function Number() {[native code]}”

    Boolean

    Boolean.toString()

    “function Boolean() {[native code]}”

    Array

    Array.toString()

    “function Array() {[native code]}”

    Function

    Function.toString()

    “function Function() {[native code]}”

    Date

    Date.toString()

    “function Date() {[native code]}”

    RegExp

    RegExp.toString()

    “function RegExp() {[native code]}”

    Error

    Error.toString()

    “function Error() {[native code]}”

    Promise

    Promise.toString()

    “function Promise() {[native code]}”

    Object

    Object.toString()

    “function Object() {[native code]}”

    Math

    Math.toString()

    “[object Math]”

    Window

    Window.toString()

    “function Window() { [native code] }”

    window

    window.toString()

    “[object Window]”

    數(shù)據(jù)類型調(diào)用 toString() 方法的返回值,由此我們看出不同的數(shù)據(jù)類型都有其自身toString()方法

    // Boolean 類型,tag 為 “Boolean”console.log(Object.prototype.toString.call(true)); // => “[object Boolean]”// Number 類型,tag 為 “Number”console.log(Object.prototype.toString.call(1)); // => “[object Boolean]”// String 類型,tag 為 “String”console.log(Object.prototype.toString.call(“”)); // => “[object String]”// Array 類型,tag 為 “String”console.log(Object.prototype.toString.call([])); // => “[object Array]”// Arguments 類型,tag 為 “Arguments”console.log(Object.prototype.toString.call((function() { return arguments;})())); // => “[object Arguments]”// Function 類型, tag 為 “Function”console.log(Object.prototype.toString.call(function(){})); // => “[object Function]”// Error 類型(包含子類型),tag 為 “Error”console.log(Object.prototype.toString.call(new Error())); // => “[object Error]”// RegExp 類型,tag 為 “RegExp”console.log(Object.prototype.toString.call(/d+/)); // => “[object RegExp]”// Date 類型,tag 為 “Date”console.log(Object.prototype.toString.call(new Date())); // => “[object Date]”// 其他類型,tag 為 “Object”console.log(Object.prototype.toString.call(new class {})); // => “[object Object]”// window 全局對象console.log(Object.prototype.toString.call(window); // => “[object Window]”)

    在 JavaScript 中,所有類都繼承于 Object,因此 toString 方法應該也被繼承了,但由上述可見事實并不像我們想的那樣,其實各數(shù)據(jù)類型使用 toString() 后的結(jié)果表現(xiàn)不一的原因在于:所有類在基礎 Object 的時候,改寫了 toString 方法。盡管如此,但 Object 原型上的方法是可以輸出數(shù)據(jù)類型的,因此我們想判斷數(shù)據(jù)類型時,也只能使用原型上的 toString 方法:Object.prototype.toString.call(object) 。

    直接調(diào)用

    toString(); // “[object Undefined]”(function(){ console.log(toString()); // [object Undefined]})();也就是說直接調(diào)用toString()方法,等價于Object.prototype.toString.call(); // “[object Undefined]”Object.prototype.toString.call(undefined); // “[object Undefined]”即:直接調(diào)用 toString() 方法這里不可以理解成為全局作用域調(diào)用 toString() 方法,即 window.toString()所以直接調(diào)用 toString() 應該就是變相的 undefined.toString() 方法(這里說的是相當于,實際 undefined 并沒有方法,調(diào)用會報錯)。

    驗證

    // 定義一個數(shù)組var arr = [1, 2, 3]// 數(shù)組原型上是否具有 toString() 方法console.log(Array.prototype.hasOwnProperty(‘toString’)) //true// 數(shù)組直接使用自身的 toString() 方法console.log(arr.toString()) // ‘1,2,3’// delete操作符刪除數(shù)組原型上的 toString()delete Array.prototype.toString// 刪除后,數(shù)組原型上是否還具有 toString() 方法console.log(Array.prototype.hasOwnProperty(‘toString’)) //false// 刪除后的數(shù)組再次使用 toString() 時,會向上層訪問這個方法,即 Object 的 toString()console.log(arr.toString()) // ‘[object Array]’

    當我們把 Array 自身的 toString() 方法刪除之后,再次使用它時,由原型鏈它會向上查找這個方法,即 Object 的 toString(),也便將 Object 上的 toString() 方法作用在數(shù)組上,得出其數(shù)據(jù)類型 [object Array] 。

    為什么需要call/apply

    經(jīng)常有人用 toString.call/apply(類型) 去代替 Object.prototype.toString.call/apply(類型) 使用,其實這樣是不嚴謹?shù)?,容易導致一些問題,如下所示

    function toString(){ console.log(“1”)}toString(); // 1toString.call({}); // 1toString.call([]); // 1

    我們可以發(fā)現(xiàn),當我們自定義了 toString() 方法時,直接調(diào)用 toString() 方法,就不會再默認調(diào)用 Object 類的 toString() 方法,而是會使用我們自定義的方法,這樣可能得不到我們想要的結(jié)果,所以我們還是應當盡量使用 Object.prototype.toString.call/apply(類型)。

    正因為 Object.prototype.toString() 本身允許被重寫,像 Array、Boolean、Number 的 toString 就被重寫過,所以需要調(diào)用 Object.prototype.toString.call(arg) 或 Object.prototype.toString.apply(arg) 或 Reflect.apply() 來判斷 arg 的類型,call 將 arg 的上下文指向 Object,所以 arg 執(zhí)行了 Object 的 toString() 方法。

    至于 call,就是改變對象的 this 指向,當一個對象想調(diào)用另一個對象的方法,可以通過 call 或者 apply 改變其 this 指向,將其 this 指向擁有此方法的對象,就可以調(diào)用該方法了。

    var x = { toString() { return “X”; },};x.toString(); // => “X”Object.prototype.toString.call(x); // => “[object Object]”Object.prototype.toString.apply(x); // => “[object Object]”Reflect.apply(Object.prototype.toString, x, []); // => “[object Object]”

    判斷原生JSON對象

    var isNativeJSON = window.JSON && Object.prototype.toString.call(JSON);console.log(isNativeJSON); // 輸出結(jié)果為 “[object JSON]” 說明JSON是原生的,否則不是;

    鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權歸原作者所有,如有侵權請聯(lián)系管理員(admin#wlmqw.com)刪除。
    用戶投稿
    上一篇 2022年6月14日 09:10
    下一篇 2022年6月14日 09:11

    相關推薦

    聯(lián)系我們

    聯(lián)系郵箱:admin#wlmqw.com
    工作時間:周一至周五,10:30-18:30,節(jié)假日休息