中文字幕日韩精品一区二区免费_精品一区二区三区国产精品无卡在_国精品无码专区一区二区三区_国产αv三级中文在线

如何理解toString與valueOf

這篇文章主要介紹“如何理解toString與valueOf”,在日常操作中,相信很多人在如何理解toString與valueOf問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解toString與valueOf”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

我們提供的服務有:成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、陸川ssl等。為上1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術(shù)的陸川網(wǎng)站制作公司

基本上,所有JS數(shù)據(jù)類型都擁有這兩個方法,null除外。它們倆是位于原型鏈上的方法,也是為了解決javascript值運算與顯示的問題。

valueOf 和 toString 幾乎都是在出現(xiàn)操作符(+-*/==><)時被調(diào)用(隱式轉(zhuǎn)換)。

toString

返回一個表示該對象的字符串,當對象表示為文本值或以期望的字符串方式被引用時,toString方法被自動調(diào)用。

1. 手動調(diào)用看看什么效果

嗯,跟介紹的一樣,沒騙人,全部都轉(zhuǎn)成了字符串。

比較特殊的地方就是,表示對象的時候,變成[object Object],表示數(shù)組的時候,就變成數(shù)組內(nèi)容以逗號連接的字符串,相當于Array.join(',')。

let a = {}  let b = [1, 2, 3]  let c = '123'  let d = function(){ console.log('fn') } console.log(a.toString())   // '[object Object]'  console.log(b.toString())   // '1,2,3'  console.log(c.toString())   // '123'  console.log(d.toString())   // 'function(){ console.log('fn') }'

2. 最精準的類型判斷

這種屬于更精確的判斷方式,在某種場合會比使用 typeof & instanceof 來的更高效和準確些。

toString.call(()=>{})       // [object Function]  toString.call({})           // [object Object]  toString.call([])           // [object Array]  toString.call('')           // [object String]  toString.call(22)           // [object Number]  toString.call(undefined)    // [object undefined]  toString.call(null)         // [object null]  toString.call(new Date)     // [object Date]  toString.call(Math)         // [object Math]  toString.call(window)       // [object Window]

3. 什么時候會自動調(diào)用呢

使用操作符的時候,如果其中一邊為對象,則會先調(diào)用toSting方法,也就是隱式轉(zhuǎn)換,然后再進行操作。

let c = [1, 2, 3]  let d = {a:2}  Object.prototype.toString = function(){      console.log('Object')  }  Array.prototype.toString = function(){      console.log('Array')      return this.join(',')   // 返回toString的默認值(下面測試)  }  Number.prototype.toString = function(){      console.log('Number')  }  String.prototype.toString = function(){      console.log('String')  }  console.log(2 + 1)  // 3  console.log('s')    // 's'  console.log('s'+2)  // 's2'  console.log(c < 2)  // false        (一次 => 'Array')  console.log(c + c)  // "1,2,31,2,3" (兩次 => 'Array')  console.log(d > d)  // false        (兩次 => 'Object')

4. 重寫toString方法

既然知道了有 toString 這個默認方法,那我們也可以來重寫這個方法

class A {      constructor(count) {          this.count = count      }      toString() {          return '我有這么多錢:' + this.count      }  }  let a = new A(100)  console.log(a)              // A {count: 100}  console.log(a.toString())   // 我有這么多錢:100  console.log(a + 1)          // 我有這么多錢:1001

Nice.

valueOf

返回當前對象的原始值。

具體功能與toString大同小異,同樣具有以上的自動調(diào)用和重寫方法。

這里就沒什么好說的了,主要為兩者間的區(qū)別,有請繼續(xù)往下看??

let c = [1, 2, 3]  let d = {a:2}  console.log(c.valueOf())    // [1, 2, 3]  console.log(d.valueOf())    // {a:2}

兩者區(qū)別

  •  共同點:在輸出對象時會自動調(diào)用。

  •  不同點:默認返回值不同,且存在優(yōu)先級關(guān)系。

二者并存的情況下,在數(shù)值運算中,優(yōu)先調(diào)用了valueOf,字符串運算中,優(yōu)先調(diào)用了toString。

看代碼方可知曉:

class A {      valueOf() {          return 2      }      toString() {          return '哈哈哈'      }  }  let a = new A()  console.log(String(a))  // '哈哈哈'   => (toString)  console.log(Number(a))  // 2         => (valueOf)  console.log(a + '22')   // '222'     => (valueOf)  console.log(a == 2)     // true      => (valueOf)  console.log(a === 2)    // false     => (嚴格等于不會觸發(fā)隱式轉(zhuǎn)換)

結(jié)果給人的感覺是,如果轉(zhuǎn)換為字符串時調(diào)用toString方法,如果是轉(zhuǎn)換為數(shù)值時則調(diào)用valueOf方法。

但其中的 a + '22' 很不和諧,字符串合拼應該是調(diào)用toString方法。為了追究真相,我們需要更嚴謹?shù)膶嶒灐?/p>

  •  暫且先把 valueOf 方法去掉 

class A {      toString() {          return '哈哈哈'      }  }  let a = new A()  console.log(String(a))  // '哈哈哈'     => (toString)  console.log(Number(a))  // NaN         => (toString)  console.log(a + '22')   // '哈哈哈22'   => (toString)  console.log(a == 2)     // false       => (toString)
  •  去掉 toString 方法看看 

class A {      valueOf() {          return 2      }  }  let a = new A()  console.log(String(a))  // '[object Object]'    => (toString)  console.log(Number(a))  // 2                    => (valueOf)  console.log(a + '22')   // '222'                => (valueOf)  console.log(a == 2)     // true                 => (valueOf)

發(fā)現(xiàn)有點不同吧?!它沒有像上面 toString 那樣統(tǒng)一規(guī)整。對于那個 [object Object],我估計是從 Object 那里繼承過來的,我們再去掉它看看。

class A {      valueOf() {          return 2      }  }  let a = new A()  Object.prototype.toString = null;   console.log(String(a))  // 2        => (valueOf)  console.log(Number(a))  // 2        => (valueOf)  console.log(a + '22')   // '222'    => (valueOf)  console.log(a == 2)     // true     => (valueOf)

總結(jié):valueOf偏向于運算,toString偏向于顯示。

  1.  在進行對象轉(zhuǎn)換時,將優(yōu)先調(diào)用toString方法,如若沒有重寫 toString,將調(diào)用 valueOf 方法;如果兩個方法都沒有重寫,則按Object的toString輸出。

  2.  在進行強轉(zhuǎn)字符串類型時,將優(yōu)先調(diào)用 toString 方法,強轉(zhuǎn)為數(shù)字時優(yōu)先調(diào)用 valueOf。

  3.  使用運算操作符的情況下,valueOf的優(yōu)先級高于toString。

[Symbol.toPrimitive]

MDN:Symbol.toPrimitive 是一個內(nèi)置的 Symbol 值,它是作為對象的函數(shù)值屬性存在的,當一個對象轉(zhuǎn)換為對應的原始值時,會調(diào)用此函數(shù)。

是不是有點懵???把它當做一個函數(shù)就行了~~

  •  作用:同valueOf()和toString()一樣,但是優(yōu)先級要高于這兩者;

  •  該函數(shù)被調(diào)用時,會被傳遞一個字符串參數(shù)

  hint

  ,表示當前運算的模式,一共有三種模式:

  •  string:字符串類型

  •  number:數(shù)字類型

  •  default:默認

下面來看看實現(xiàn)吧:

class A {      constructor(count) {          this.count = count      }      valueOf() {          return 2      }      toString() {          return '哈哈哈'      }      // 我在這里      [Symbol.toPrimitive](hint) {          if (hint == "number") {              return 10;          }          if (hint == "string") {              return "Hello Libai";          }          return true;      }  }  const a = new A(10)  console.log(`${a}`)     // 'Hello Libai' => (hint == "string")  console.log(String(a))  // 'Hello Libai' => (hint == "string")  console.log(+a)         // 10            => (hint == "number")  console.log(a * 20)     // 200           => (hint == "number") console.log(a / 20)     // 0.5           => (hint == "number")  console.log(Number(a))  // 10            => (hint == "number")  console.log(a + '22')   // 'true22'      => (hint == "default")  console.log(a == 10)     // false        => (hint == "default")

比較特殊的是(+)拼接符,這個屬于default的模式。

劃重點:此方法不兼容IE,尷尬到我不想寫出來了~~

面試題分析

以下幾道大廠必考的面試題,完美呈現(xiàn)出 toString 與 valueOf 的作用。

1. a===1&&a===2&&a===3 為 true

雙等號(==):會觸發(fā)隱式類型轉(zhuǎn)換,所以可以使用 valueOf 或者 toString 來實現(xiàn)。

每次判斷都會觸發(fā)valueOf方法,同時讓value+1,才能使得下次判斷成立。

class A {      constructor(value) {          this.value = value;      }      valueOf() {          return this.value++;      }  } const a = new A(1);  if (a == 1 && a == 2 && a == 3) {      console.log("Hi Libai!");  }

全等(===):嚴格等于不會進行隱式轉(zhuǎn)換,這里使用 Object.defineProperty 數(shù)據(jù)劫持的方法來實現(xiàn)

let value = 1;  Object.defineProperty(window, 'a', {      get() {          return value++      }  })  if (a === 1 && a === 2 && a === 3) {      console.log("Hi Libai!")  }

上面我們就是劫持全局window上面的a,當a每一次做判斷的時候都會觸發(fā)get屬性獲取值,并且每一次獲取值都會觸發(fā)一次函數(shù)實行一次自增,判斷三次就自增三次,所以最后會讓公式成立。

2. 實現(xiàn)一個無限累加函數(shù)

問題:用 JS 實現(xiàn)一個無限累加的函數(shù) add,示例如下:

add(1); // 1  add(1)(2);  // 3  add(1)(2)(3); // 6  add(1)(2)(3)(4); // 10   // 以此類推  function add(a) {      function sum(b) { // 使用閉包          a = b ? a + b : a; // 累加          return sum;      }      sum.toString = function() { // 只在最后一次調(diào)用          return a;      }      return sum; // 返回一個函數(shù)  }  add(1)              // 1  add(1)(2)           // 3  add(1)(2)(3)        // 6  add(1)(2)(3)(4)     // 10
  •  add函數(shù)內(nèi)部定義sum函數(shù)并返回,實現(xiàn)連續(xù)調(diào)用

  •  sum函數(shù)形成了一個閉包,每次調(diào)用進行累加值,再返回當前函數(shù)sum

  •  add()每次都會返回一個函數(shù)sum,直到最后一個沒被調(diào)用,默認會觸發(fā)toString方法,所以我們這里重寫toString方法,并返回累計的最終值a

這樣說才能理解:

add(10): 執(zhí)行函數(shù)add(10),返回了sum函數(shù),注意這一次沒有調(diào)用sum,默認執(zhí)行sum.toString方法。所以輸出10;

add(10)(20): 執(zhí)行函數(shù)add(10),返回sum(此時a為10),再執(zhí)行sum(20),此時a為30,返回sum,最后調(diào)用sum.toString()輸出30。add(10)(20)...(n)依次類推。

3. 柯里化實現(xiàn)多參累加

這里是上面累加的升級版,實現(xiàn)多參數(shù)傳遞累加。

add(1)(3,4)(3,5)    // 16  add(2)(2)(3,5)      // 12  function add(){      // 1 把所有參數(shù)轉(zhuǎn)換成數(shù)組      let args = Array.prototype.slice.call(arguments)      // 2 再次調(diào)用add函數(shù),傳遞合并當前與之前的參數(shù)      let fn = function() {          let arg_fn = Array.prototype.slice.call(arguments)          return add.apply(null, args.concat(arg_fn))      }      // 3 最后默認調(diào)用,返回合并的值      fn.toString = function() {          return args.reduce(function(a, b) {              return a + b          })      }      return fn  }  // ES6寫法  function add () {      let args = [...arguments];      let fn = function(){          return add.apply(null, args.concat([...arguments]))      }       fn.toString = () => args.reduce((a, b) => a + b)      return fn;  }

到此,關(guān)于“如何理解toString與valueOf”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

文章標題:如何理解toString與valueOf
分享鏈接:http://www.rwnh.cn/article40/jeedeo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站建設(shè)、網(wǎng)站設(shè)計企業(yè)建站、網(wǎng)站收錄、App設(shè)計網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

搜索引擎優(yōu)化
六枝特区| 玛曲县| 昌宁县| 荥经县| 车致| 阿拉善右旗| 吴桥县| 金堂县| 永城市| 玛纳斯县| 余庆县| 施秉县| 石嘴山市| 全南县| 台北县| 当雄县| 手游| 大邑县| 宝清县| 南岸区| 方城县| 仪征市| 马山县| 潜江市| 泰兴市| 弋阳县| 恩施市| 台东市| 中阳县| 崇文区| 双峰县| 昌江| 武邑县| 珲春市| 商丘市| 福海县| 汕头市| 长泰县| 公主岭市| 莱阳市| 涿州市|