系列文章
前端八股文-手写new、bind、call、apply的三两事
typeof(无法正确判断类型)
- 对于原始类型来说,除了 null 都可以显示正确的类型
- 对于对象来说,除了函数都会显示 object
- 对于null,显示 object
instanceof(原始类型无效)
用法:object(要检测的对象) instanceof constructor(某个构造函数)
描述:用来检测 constructor.prototype 是否存在于参数 object 的原型链上
重点:另外,更重要的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。其本质是在原型链上层层检索
正常使用用例:
const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true
var str = 'hello world'
str instanceof String // false
var str1 = new String('hello world')
str1 instanceof String // true
对于原始类型来说,你想直接通过 instanceof 来判断类型是不行的,当然我们还是有办法让 instanceof 判断原始类型的
class PrimitiveString {
static [Symbol.hasInstance](x) {
return typeof x === 'string'
}
}
console.log('hello world' instanceof PrimitiveString) // true
重点代码用例:
function Aoo() {} // 构造函数 Aoo
function Foo() {} // 构造函数 Foo
Foo.prototype = new Aoo(); //将Aoo的实例赋值给Foo的原型
var foo = new Foo(); // 构造函数Foo的实例
// foo.__proto__ === Foo.prototype
// foo.__proto__.__proto__ === Aoo.prototype
console.log(foo.__proto__ === Foo.prototype); // __proto__指向构造函数的原型
console.log(foo.__proto__.__proto__ === Aoo.prototype);
console.log(foo instanceof Foo) //true Foo的原型是挂载在实例
console.log(foo instanceof Aoo)//true // Foo.prototype往上接着找___proto__,找到Aoo.prototype,因而为true
Object.prototype.toString.call()
toString方法可以将对象转化为形如"[object XXX]" 的字符串。
大多数对象,toString() 方法都是重写了的,这时,需要用 call() 或 Reflect.apply() 等方法来调用。
对于 Object.prototype.toString.call(arg),若参数为 null 或 undefined,直接返回结果。
若参数不为 null 或 undefined,则将参数转为对象,再作判断。
注意:原始数据类型,在调用方法时,会先将原始数据类型转换为包装对象再进行方法调用
var a = '1'
a.length => new String('1').length
核心原理
转为对象后,取得该对象的 [Symbol.toStringTag] 属性值(可能会遍历原型链)作为 tag,如无该属性,或该属性值不为字符串类型,则依下表取得 tag, 然后返回 "[object " + tag + "]" 形式的字符串。属性值期望是一个字符串,否则会被忽略。
类型检测列表
// Boolean 类型,tag 为 "Boolean"
Object.prototype.toString.call(true); // => "[object Boolean]"
// Number 类型,tag 为 "Number"
Object.prototype.toString.call(1); // => "[object Boolean]"
// String 类型,tag 为 "String"
Object.prototype.toString.call(""); // => "[object String]"
// Array 类型,tag 为 "String"
Object.prototype.toString.call([]); // => "[object Array]"
// Arguments 类型,tag 为 "Arguments"
Object.prototype.toString.call((function() {
return arguments;
})()); // => "[object Arguments]"
// Function 类型, tag 为 "Function"
Object.prototype.toString.call(function(){}); // => "[object Function]"
// Error 类型(包含子类型),tag 为 "Error"
Object.prototype.toString.call(new Error()); // => "[object Error]"
// RegExp 类型,tag 为 "RegExp"
Object.prototype.toString.call(/\d+/); // => "[object RegExp]"
// Date 类型,tag 为 "Date"
Object.prototype.toString.call(new Date()); // => "[object Date]"
// 其他类型,tag 为 "Object"
Object.prototype.toString.call(new class {}); // => "[object Object]"
重写Symbol.toStringTag的示例
var o1 = { [Symbol.toStringTag]: "A" };
var o2 = { [Symbol.toStringTag]: null };
Object.prototype.toString.call(o1); // => "[object A]"
Object.prototype.toString.call(o2); // => "[object Object]"