toString 实现无限累加

时间:2021-1-8 作者:admin

题目

用 js 实现无限累加

add(1)
add(1)(2)
add(1)(2)(3)

function add() {
  const args = [].slice.call(arguments)
  const fn = function() {
      const fn_args = [].slice.call(arguments)
      return add.apply(null, args.concat(fn_args))
  }
  fn.toString = function() {
      return args.reduce((res, cur) => (res + cur))
  }
  return fn
}

+ add(1) // 1
+ add(1, 2) // 3
+ add(1)(2)(3) // 6

概念

object.toString() 返回一个表示该对象的字符串。

object.valueOf() 返回指定对象的原始值。

可重写 toString、valueOf 方法覆盖

不同类型对象的 valueOf() 方法的返回值

对象 返回值
Array 返回数组对象本身。
Boolean 布尔值。
Date 存储的时间是从 1970 年 1 月 1 日午夜开始计的毫秒数 UTC。
Function 函数本身。
Number 数字值。
Object 对象本身。这是默认情况。
String 字符串值。
Math 和 Error 对象没有 valueOf 方法。

参考:toString
valueOf
typeof
instanceof
基本类型

使用

object.toString() 判断类型

function getType(obj) {
    const str = Object.prototype.toString.call(obj)
    const map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Function]': 'function',
        '[object Array]': 'array',
        '[object Date]': 'date',
        '[object RegExp]': 'regExp',
        '[object Undefined]': 'undefined',
        '[object Null]': 'null',
        '[object Object]': 'object',
        '[object Map]': 'map',
        '[object Set]': 'set'
    }
    return map[str]
}

function getType(obj) {
    return Object.prototype.toString.call(obj).slice(8, -1).toLowercase()
}

function isType(obj, t) {
    return Object.prototype.toString.call(obj).slice(8, -1).toLowercase() === t.toLowercase()
}

对比 typeof instanceof

typeof

常用来判断基本类型 string/number/boolean/symbol/bigint 以及 function

typeof null === 'object' // JavaScript 诞生以来便如此
typeof 返回值
Undefined “undefined”
Null “object”
Boolean “boolean”
Number “number”
BigInt(ECMAScript 2020 新增) “bigint”
String “string”
Symbol (ECMAScript 2015 新增) “symbol”
Function 对象 (按照 ECMA-262 规范实现 [[Call]]) “function”
其他任何对象 “object”
宿主对象(由 JS 环境提供) 取决于具体实现
instanceof

obj instanceof Object

检测构造函数的 prototype 属性是否出现在某个实例对象的原型链

class O {
    constructor() {}
}

class A extends O {}
const a = new A()

a instanceof A // true
a instanceof O // true

instanceof 简易实现

// 原理: a.__proto__(.__proto__....) === A.prototype
function _instanceof(a, A) {
    const F = A.prototype
    let obj = a.__proto__

    while(true) {
        if (obj === null) {
            return false
        }
        if (obj === F) {
            return true
        }
        obj = obj.__proto__
    }
}

类型转换-对象转原始类型

对象在转换类型的时候,会调用内置的 [[ToPrimitive]] 函数。

(可以重写 Symbol.toPrimitive ,该方法在转原始类型时调用优先级最高。toPrimitive

对于该函数来说,算法逻辑一般来说如下:

  • 如果已经是原始类型了,那就不需要转换了
  • 调用 object.valueOf(),如果转换为基础类型,就返回转换的值
  • 调用 object.toString(),如果转换为基础类型,就返回转换的值
  • 如果都没有返回原始类型,就会报错
const a = {
  valueOf() {
    return 1
  },
  toString() {
    return '2'
  }
}

+ a // 1
1 + a // 2
1 > a // false
1 == a // true
1 === a // false

扩展:
相等性判断

ES2015中有四种相等算法:

  • 抽象(非严格)相等比较 (==)
  • 严格相等比较 (===): 用于 Array.prototype.indexOf, Array.prototype.lastIndexOf, 和 case-matching
  • 同值零: 用于 %TypedArray% 和 ArrayBuffer 构造函数、以及Map和Set操作, 并将用于 ES2016/ES7 中的String.prototype.includes
  • 同值: 用于所有其他地方

JavaScript提供三种不同的值比较操作:

  • === 严格相等比较
  • == 抽象相等比较
  • Object.is
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。