JS容易出现误区的操作符
类型判断
typeof
typeof
typeof
操作符返回一个字符串,表示未经计算的操作数的类型。
typeof
运算符,判断数据类型,对于基本类型,返回基本类型,对于引用类型的,不管哪一种引用类型,都返回'object'
。typeof
除了null
返回'object'
,和函数返回'function'
,其他都能正确返回,凡是引用类型返回都是'object'
。
typeof
对new
一个构造函数生成内容的判断需要特别注意
typeof
对new
一个构造函数生成内容的判断需要特别注意var str = new String('String');
var num = new Number(100);
typeof str; // 返回 'object'
typeof num; // 返回 'object'
var func = new Function();
typeof func; // 返回 'function'
因此,通过typeof
判断基本数据类型,也会返回不一样的结果,需要特别注意,在不确定是否是基本数据类型的场景下慎用,不过大部分场景中很少存在通过构造函数生成基本数据类型,可以使用typeof
判断。
instanceof
instanceof
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。通常用来判断实例是否属于一个父类型。
instanceof
如何实现这样的功能,语言规范里面有详细的介绍,这里截取部分:
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
var O = R.prototype;// 取 R 的显示原型对象
L = L.__proto__;// 取 L 的隐式原型对象
while (true) {
if (L === null)
return false;
if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
instanceof
也可以用来判断一些内置对象类型,比如function instanceof Function
, reg instanceof RegExp
等
const reg = new RegExp(/e/i);
reg instanceof RegExg; // true
Object.prototype.toString()
Object.prototype.toString()
toString
也可以做为类型判断, 返回一个类似 [Object Type]
的字符串,和typeof
不一样的地方在于能判断null
和Date
、Math
等内置对象。但是对于new
一个构造函数,和typeof
判定是一样的。
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
对象上指定属性判断
in
in
如果指定的属性在指定的对象或其原型链中,则in 运算符返回true。
重点是需要注意的是原型链存在指定的属性,也会返回true
,所以in
一般用来判断纯粹的对象。
Object.prototype.hasOwnProperty()
Object.prototype.hasOwnProperty()
当有这种需求时,只能使用Object.prototype.hasOwnProperty()
来判断,这是一个比较蛋疼的方式。
let hasOwnProperty = Object.prototype.hasOwnProperty
if (hasOwnProperty.call(obj, "foo")) {
console.log("has property foo")
}
Object.hasOwn()
Object.hasOwn()
因此,在ES2022版本,新增了一个API,Object.hasOwn()
,用来解决判断对象上是否有指定属性,不会像原型链查找
let object = { foo: false }
Object.hasOwn(object, "foo") // true
let object2 = Object.create({ foo: true })
Object.hasOwn(object2, "foo") // false
function Person() {
}
Person.prototype.name = 'nick';
let person = new Person();
console.log('name' in person); // true
console.log(Object.prototype.hasOwnProperty(person, 'name')); // false
console.log(Object.hasOwn(person, 'name')); // false
但是通过class
生成类,Object.hasOwn
判定为true
。
class Person {
constructor() {
this.name = 'Nike';
}
}
let person = new Person();
console.log('name' in person); // true
console.log(Object.prototype.hasOwnProperty(person, 'name')); // false
console.log(Object.hasOwn(person, 'name')); // true
由规范得到,instanceof
将表达式1的__proto__
与表达式2的prototype
进行严格相等===
比较:
如果相等返回true;如果不相等,则继续循环获取前面表达式的__proto__
,直到 Object.__proto__===null
为止返回false。
console.log(Object instanceof Object);//true
console.log(Function instanceof Function);//true
console.log(Number instanceof Number);//false
console.log(String instanceof String);//false
console.log(Function instanceof Object);//true
console.log(Foo instanceof Function);//true
console.log(Foo instanceof Foo);//false
delete
delete
delete
用于删除某个对象的属性,如果没有指向这个属性的引用,那它最终会被释放。
使用注意事项:
如果你试图删除的属性不存在,那么
delete
将不会起任何作用,但仍会返回true
如果删除属性的该对象原型链上有同名属性,delete只会删除自身属性,删除之后,对象会使用原型链上的属性。(也就是说,
delete
操作只会在自身的属性上起作用)任何用
let
或const
声明的属性不能够从它被声明的作用域中删除使用
var
声明的属性不能从全局作用域中或者函数作用域中删除不可设置的属性不能被删除
delete
删除数组对象
delete
删除数组对象delete
只能删除指定数组元素的对象,数组的大小不改变,删除后位置空余,显示undefined
,或者其他填充值。
数组方法array.splice
指定删除数组元素对象,数组大小发生变化。
Last updated