题目
用 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