<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何實現(xiàn)a===1 && a===2 && a===3返回true?

          共 5269字,需瀏覽 11分鐘

           ·

          2021-07-05 02:18

          這是一道面試題,大家先自己想一下,在什么情況下這個判斷會成立?按正常思維想,這個是不可能成立的。
          if(a == 1 && a == 2 && a == 3){   console.log(true);}//console.log(a == 1 && a == 2 && a == 3); // true

          怎么實現(xiàn)a 能與1,2,3相等呢?下面我整理一些可行的實現(xiàn)方案,希望對你有所幫助。

          方案一:重寫toString()或valueOf()

          let a = {  i: 1,  toString: function () {    return a.i++;  }}console.log(a == 1 && a == 2 && a == 3); // true

          在做判斷時,首先會調用valueOf函數(shù),數(shù)組調用valueOf后返回的還是數(shù)組本身,就會再次調用toString函數(shù),這里是重寫了toString方法,并且return的是a.i++,所以每調用一次,都會在上次的值得基礎上自加一次,
          所以結果為true。同下:

          let a = {    i: 1,    valueOf: function()  {        return this.i++;    }}console.log(a == 1 && a == 2 && a == 3); // true

          這里i定義為1,我們還可以定義正則表達式的方式來實現(xiàn),比如:

          let a = {   reg: /\d/g,   valueOf: function() {      return this.reg.exec(123)[0];   },};console.log(a == 1 && a == 2 && a == 3); // true

          方案二:數(shù)組

          數(shù)組的toString接口默認調用數(shù)組的join方法,重寫join方法。定義a為數(shù)字,每次比較時就會調用 toString()方法,我們把數(shù)組的shift方法覆蓋toString即可:

          let a = [1,2,3];a.toString = a.shift;console.log(a == 1 && a == 2 && a == 3); // true

          當然把toString改為valueOf也是一樣效果:

          let a = [1,2,3];a. valueOf  = a.shift;console.log(a == 1 && a == 2 && a == 3); // true

          結合方案一,我們還可以這樣來實現(xiàn):

          let a = {   value:[3,2,1],   valueOf:function() {  //或者toString         return this.value.pop();     },}console.log(a == 1 && a == 2 && a == 3); // true

          方案三:數(shù)字變量

          我們將數(shù)字作為變量名,讓a=1,讓數(shù)字變量=a。

          let a = 1;let 1 = a;let 2 = a ;let 3 = a ;console.log( a ==?1 && a ==?2 && a ==?3 ); // true

          方案四:使用Object.defineProperty()

          Object.defineProperty()用于定義對象中的屬性,接收三個參數(shù):object對象、對象中的屬性,屬性描述符。屬性描述符中get:訪問該屬性時自動調用,vue3之前的版本實現(xiàn)雙向綁定主要就用到了它。

          Object.defineProperty(this, 'a', {    get: function () {        return this.value = this.value ? (this.value += 1) : 1    }})console.log(a===1 && a===2 && a===3) //true

          或者

          var  _a = 1;Object.defineProperty(this,'a',{  get:function(){    return _a++  }})console.log(a===1 && a===2 && a===3)//true

          方案五:使用ES6 Proxy

          es6的proxy用于在目標對象的外層搭建了一層攔截,外界對目標對象的某些操作,必須通過這層攔截。我們這里重新定義了屬性的讀取(get)行為。

          let a = new Proxy({ i: 0 }, {    get: (target, name) => name === Symbol.toPrimitive ? () => ++target.i : target[name],});console.log(a == 1 && a == 2 && a == 3);    // true

          方案六:使用Reflect.defineProperty

          我們還可以通過Reflect.defineProperty定義一個全局的屬性_a,當屬性_a被訪問的時候就會調用上面定義的getter方法,所以和上面對象的隱式類型轉換過程是一樣的。

          let _a= 1;Reflect.defineProperty(this, 'a', {    get() {        return _a++;    }});console.log(a === 1 && a === 2 && a === 3);//true

          方案七:Race Condition(競態(tài)條件)

          這是在底層的內存上修改一個變量的值,而不是通過一些所謂的技巧去讓上面的表達式成立。而且這在現(xiàn)實的開發(fā)中是可能會出現(xiàn)的一種情況。在進入下面的講解之前,我們需要先了解一些前置的知識點。

          SharedArrayBuffer

          SharedArrayBuffer對象用來表示一個通用的,固定長度的原始二進制數(shù)據(jù)緩沖區(qū),類似于 ArrayBuffer對象,它們都可以用來在共享內存上創(chuàng)建視圖。與ArrayBuffer不同的是SharedArrayBuffer不能被分離。

          Web Worker

          Web Worker為Web內容在后臺線程中運行腳本提供了一種簡單的方法。線程可以執(zhí)行任務而不干擾用戶界面。

          此外,他們可以使用XMLHttpRequest執(zhí)行 I/O (盡管responseXML和channel屬性總是為空)。

          一旦創(chuàng)建, 一個worker 可以將消息發(fā)送到創(chuàng)建它的JavaScript代碼, 通過將消息發(fā)布到該代碼指定的事件處理程序(反之亦然)。詳情可以參考使用 Web Workers。

          了解了前置的知識我們直接看接下來的代碼實現(xiàn)吧。

          index.js

          // index.jsconst worker = new Worker('./worker.js');const competitors = [   new Worker('./competitor.js'),   new Worker('./competitor.js'),];const sab = new SharedArrayBuffer(1);worker.postMessage(sab);competitors.forEach(w => {   w.postMessage(sab);});

          worker.js

          // worker.jsself.onmessage = ({ data }) => {   const arr = new Uint8Array(data);   Reflect.defineProperty(self, 'a', {      get() {         return arr[0];      },   });   let count = 0;   while (!(a === 1 && a === 2 && a === 3)) {      count++;      if (count % 1e8 === 0) console.log('running...');   }   console.log(`After ${count} times, a === 1 && a === 2 && a === 3 is true!`);};

          competitor.js

          // competitor.jsself.onmessage = ({ data }) => {   const arr = new Uint8Array(data);   setInterval(() => {      arr[0] = Math.floor(Math.random() * 3) + 1;   });};

          在開始深入上面的代碼之前,你可以在本地運行一下上面的代碼,在看到結果之前可能需要等上一小會。

          或者直接在這里打開瀏覽器的控制臺看一下運行的結果。

          需要注意的是,因為SharedArrayBuffer現(xiàn)在僅在Chrome瀏覽器中被支持,所以需要我們使用Chrome瀏覽器來運行這個程序。

          運行之后你會在控制臺看到類似如下的結果:

          158 running...After 15838097593 times, a === 1 && a === 2 && a === 3 is true!

          我們可以看到,運行了15838097593次才出現(xiàn)一次相等。不同的電腦運行這個程序所需要的時間是不一樣的,就算同一臺機器每次運行的結果也是不一樣的。

          下面我們來深入的講解一下上面的代碼,首先我們在index.js中創(chuàng)建了三個worker,其中一個worker用來進行獲取a的值,并且一直循環(huán)進行比較。直到a === 1 && a === 2 && a === 3成立,才退出循環(huán)。

          另外兩個worker用來制造Race Condition,這兩個worker一直在對同一個地址的數(shù)據(jù)進行修改。

          在index.js中,我們使用SharedArrayBuffer申請了一個字節(jié)大小的一段連續(xù)的共享內存。

          然后我們通過worker的postMessage方法將這個內存的地址傳遞給了3個worker。

          在這里我們需要注意,一般情況下,通過Worker的postMessage傳遞的數(shù)據(jù)要么是可以由結構化克隆算法處理的值(這種情況下是值的復制),要么是Transferable類型的對象(這種情況下,一個對象的所有權被轉移,在發(fā)送它的上下文中將變?yōu)椴豢捎茫⑶抑挥性谒话l(fā)送到的worker中可用)。

          更多詳細內容可以參考Worker.postMessage() 。

          但是如果我們傳遞的對象是SharedArrayBuffer類型的對象,那么這個對象的代表的是一段共享的內存,是可以在主線程和接收這個對象的Worker中共享的。

          在competitor.js中,我們獲取到了傳遞過來的SharedArrayBuffer對象,因為我們不可以直接操作這段內存,需要在這段內存上創(chuàng)建一個視圖,然后才能夠對這段內存做處理。

          我們使用Uint8Array創(chuàng)建了一個數(shù)組,然后設置了一個定時器一直對數(shù)組中的第一個元素進行賦值操作,賦值是隨機的,可以是1,2,3中的任何一個值。

          因為我們有兩個worker同時在做這個操作,所以就形成了Race Condition。

          在worker.js中,我們同樣在傳遞過來的SharedArrayBuffer對象上創(chuàng)建了一個Uint8Array的視圖。然后在全局定義了一個屬性a,a的值是讀取Uint8Array數(shù)組的第一個元素值。

          然后是一個while循環(huán),一直在對表達式a === 1 && a === 2 && a === 3進行求值,直到這個表達式的值為true,就退出循環(huán)。

          本文完~

          學習更多技能

          請點擊下方公眾號



          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产精品稀缺盗摄盗拍 | 国产精品内射视频免费 | 亚洲视频 | 国产女女在线观看 | 日本精品一区二区 |