题目
用 js 实现无限累加
add(1) add(1)(2) add(1)(2)(3)
function add(...args) {
const fn = function(...fn_args) {
return add.apply(null, [...args, ...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
另一种解法
function curry(fn) {
let allArgs = []
return function tmp(...args) {
if (args.length) {
allArgs = [...allArgs, ...args]
return tmp
} else {
const res = fn.apply(null, allArgs)
allArgs = []
return res
}
}
}
function add(...args) {
return args.reduce((res, cur) => (res + cur))
}
const addFn = curry(add)
addFn(1)() // 1
addFn(1, 2)() // 3
addFn(1)(2, 3)() // 6
addFn(1)(2, 3)(4)() // 10
概念
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