国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

魔幻語言 JavaScript 系列之 a == true && a == fals

BDEEFE / 722人閱讀

摘要:稍后我們再詳細剖析,接下來先看一個問題。還內建了一些在之前沒有暴露給開發者的,它們代表了內部語言行為。使用,可能有不少朋友一開始就想到這種方式,簡單貼一下閱讀更多

在 JavaScript 環境下,可以讓表達式 a == true && a == false 為 true 嗎?

就像下面這樣,可以在控制臺打印出 ’yeah":

// code here
if (a == true && a == false) {
    console.log("yeah");
}

JavaScript 是一門類型松散的語言,在使用 == 進行比較時,倘若左右類型不一致,是會進行類型裝換的。首先來了解一下寬松相等的概念,

寬松相等 ==

先看看 ECMA 5.1 的規范,包含 toPrimitive:

規范 11.9.3 The Abstract Equality Comparison Algorithm

If Type(x) is the same as Type(y), then

If Type(x) is Undefined, return true.

If Type(x) is Null, return true.

If Type(x) is Number, then

If x is NaN, return false.

If y is NaN, return false.

If x is the same Number value as y, return true.

If x is +0 and y is ?0, return true.

If x is ?0 and y is +0, return true.

Return false.

If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.

If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.

Return true if x and y refer to the same object. Otherwise, return false.

If x is null and y is undefined, return true.

If x is undefined and y is null, return true.

If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y).

If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.

If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

If Type(x) is either String or Number and Type(y) is Object, return the result of the comparison x == ToPrimitive(y).

If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

Return false.

9.1 ToPrimitive

Table 10 — ToPrimitive Conversions

Input Type Result
Undefined The result equals the input argument (no conversion).
Null The result equals the input argument (no conversion).
Boolean The result equals the input argument (no conversion).
Number The result equals the input argument (no conversion).
String The result equals the input argument (no conversion).
Object Return a default value for the Object. The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType. The behaviour of the [[DefaultValue]] internal method is defined by this specification for all native ECMAScript objects in 8.12.8.
稍作總結

對于下述表達式:

x == y

類型相同,判斷的就是 x === y

類型不同

如果 x,y 其中一個是布爾值,將這個布爾值進行 ToNumber 操作

如果 x,y 其中一個是字符串,將這個字符串進行 ToNumber 操作

若果 x,y 一方為對象,將這個對象進行 ToPrimitive 操作

至于 ToPrimitive,即求原始值,可以簡單理解為進行 valueOf()toString() 操作。

稍后我們再詳細剖析,接下來先看一個問題。

Question:是否存在這樣一個變量,滿足 x == !x

就像這樣:

// code here
if (x == !x) {
    console.log("yeah");
}

可能很多人會想到下面這個,畢竟我們也曾熱衷于各種奇技淫巧:

[] == ![] // true

但答案絕不僅僅局限于此,比如:

var x = new Boolean(false);


if (x == !x) {
    console.log("yeah");
}

理解這個問題,基本上下面的這些例子都不是問題了。

寬松相等的栗子
9 == "9"

9 == "9x"

9 == true

9 == undefined

9 == null

0 == undefined

0 == null

undefined == null

0 == false

"" == false

"1" == true

"9" == true

9 == [9]

"9" == [9]

"9" == [9, 4]

"9,4" == [9, 4]

[] == []

[] == ![]

![] == ![]

[] == {}

[] == !{}

{} == ![]

{} == {}

{} == !{}

9 == { toString() { return 9 }}

9 == { valueOf() { return 9 }}

9 == { a: 9 }

9 == {}

"[object Object]" == {}

在來看看什么是 ToPrimitive

ToPrimitive

貼個規范:8.12.8 [[DefaultValue]] (hint)

如果是 Date 求原始值,則 hint 是 String,其他均為 Number,即先調用 valueOf() 再調用 toString()

如果 hint 為 Number,具體過程如下:

調用對象的 valueOf() 方法,如果值是原值則返回

否則,調用對象的 toString() 方法,如果值是原值則返回

否則,拋出 TypeError 錯誤

// valueOf 和 toString 的調用順序
var a = {
    valueOf() {
        console.log("valueof")
        return []
    },
    toString() {
        console.log("toString")
        return {}
    }
}

a == 0
// valueof
// toString
// Uncaught TypeError: Cannot convert object to primitive value


// Date 類型先 toString,后 valueOf
var t = new Date("2018/04/01");
t.valueOf = function() {
    console.log("valueof")
    return []
}
t.toString = function() {
    console.log("toString")
    return {}
}
t == 0
// toString
// valueof
// Uncaught TypeError: Cannot convert object to primitive value

到目前為止,上面的都是 ES5 的規范,那么在 ES6 中,有什么變化呢

ES6 中 ToPrimitive

7.1.1ToPrimitive ( input [, PreferredType] )

在 ES6 中嗎,是可以自定義 @@toPrimitive 方法的,是 Well-Known Symbols(§6.1.5.1)中的一個。JavaScript 還內建了一些在 ECMAScript 5 之前沒有暴露給開發者的 symbol,它們代表了內部語言行為。

// 沒有 Symbol.toPrimitive 屬性的對象
var obj1 = {};
console.log(+obj1); // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"

// 擁有 Symbol.toPrimitive 屬性的對象
var obj2 = {
    [Symbol.toPrimitive](hint) {
        if (hint == "number") {
            return 10;
        }
        if (hint == "string") {
            return "hello";
        }
        return true;
    }
};
console.log(+obj2); // 10 -- hint is "number"
console.log(`${obj2}`); // "hello" -- hint is "string"
console.log(obj2 + ""); // "true" -- hint is "default"

有了上述鋪墊,答案就呼之欲出了

最初題目的答案
var a = {
    flag: false,
    toString() {
        return this.flag = !this.flag;
    }
}

或者使用 valueOf()

var a = {
    flag: false,
    valueOf() {
        return this.flag = !this.flag;
    }
}

或者是直接改變 ToPrimitive 行為:

// 其實只需設置 default 即可
var a = {
    flag: false,
    [Symbol.toPrimitive](hint) {
        if (hint === "number") {
            return 10
        }
        if (hint === "string") {
            return "hello"
        }
        return this.flag = !this.flag
    }
}
如果是嚴格相等呢

但是,有沒有辦法是嚴格相等,即:

// code here
if (a === true && a === false) {
console.log("yeah");
}

答案是:有。

使用 defineProperty,可能有不少朋友一開始就想到這種方式,簡單貼一下:

let flag = false
Object.defineProperty(window, "a", {
    get() {
        return (flag = !flag)
    }
})

if (a === true && a === false) {
    console.log("yeah");
}
閱讀更多

Can (a== 1 && a ==2 && a==3) ever evaluate to true?

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93950.html

相關文章

  • 魔幻語言 JavaScript 系列類型轉換、寬松相等以及原始值

    摘要:通過使用其構造函數,可以將一個值的類型轉換為另一種類型。如果使用兩次,可用于將該值轉換為相應的布爾值。 編譯自:[1] + [2] – [3] === 9!? Looking into assembly code of coercion.全文從兩個題目來介紹類型轉換、寬松相等以及原始值的概念: [1] + [2] – [3] === 9 如果讓 a == true && a == fa...

    li21 評論0 收藏0
  • 魔幻語言 JavaScript 系列 call、bind 以及上下文

    摘要:那么,它到底是如何工作的呢讓我們從一種更簡單的實現開始實際上這種實現代碼更短,并且更易讀是函數原型中的一個函數,它調用函數,使用第一個參數作為參數,并傳遞剩余參數作為被調用函數的參數。 原文:The Most Clever Line of JavaScript 作者:Seva Zaikov 原文 最近 一個朋友 發給我一段非常有趣的 JavaScript 代碼,是他在某個 開源庫中...

    cuieney 評論0 收藏0
  • JS系列call & apply & bind

    摘要:參考鏈接在中,和是對象自帶的三個方法,都是為了改變函數體內部的指向。返回值是函數方法不會立即執行,而是返回一個改變了上下文后的函數。而原函數中的并沒有被改變,依舊指向全局對象。原因是,在中,多次是無效的。 參考鏈接:https://juejin.im/post/59bfe8... 在JavaScript中,call、apply和bind是Function對象自帶的三個方法,都是為了改變...

    xiaochao 評論0 收藏0
  • javascript中的constructor&&prototype

    摘要:于是退而求其次叫為類的構造函數。如果這個函數被用在創建自定義對象的場景中,我們稱這個函數為構造函數。遇到的問題始終指向創建當前對象的構造函數。 Object.constructor,prototype 對象的prototype和constructor是兩個重要的屬性,他們總是成對出現,提到constructor的地方,不得不涉及到另外一個非常重要的屬性prototype,它是js中基于...

    huaixiaoz 評論0 收藏0
  • 前端跨域原因&&方案&&原理

    摘要:于是乎同源策略應運而生主要限制在于和無法讀取。怎么繞過同源策略首先一般來說協議和端口造成的跨域問題大部分方法是沒有辦法繞過的。二級域名是寄存在主域名之下的域名。當主域名受到懲罰二級域名也會連帶懲罰。 前言 這是一道前端跨不過躲不掉面試必備的知識,掙扎多年沒能做到刻骨銘心深入脊髓,只能好好寫篇博文記錄起來了; 什么是跨域? 廣義來說,A域執行的文檔腳本試圖去請求B域下的資源是不被允許的,...

    Zack 評論0 收藏0

發表評論

0條評論

BDEEFE

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<