原生JS灵魂之问——你真的懂这些JS吗?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_43624878/article/details/102669091

最近在看ES6(可能是初到公司的缘故,处于振奋与繁忙的事带来的无力之中。。。不过还是坚持认真阅读了《深入浅出ES6》,真心觉得是本好书),里面一些内容会时不时让人有“恍然大悟”之感。

先说下 JS数据类型:

原始数据类型和引用数据类型

原始数据类型 (6种)

  • boolean
  • null
  • undefined
  • number
  • string
  • symbol

引用数据类型:

  • 对象 object(包括object,Array,RegExp,Date,Math…)
  • 函数 Function

这里的“null”是个对象吗?
我们 console.log(typeof null); ,会输出:object。但这只是JS存在已久的Bug,它不是对象。
但JS之初用的32位系统,为了性能考虑使用低位存储变量的类型信息,000开头代表是对象,然而null全0,所以,就将其判为object。

typeof能否正确判断类型?

我们知道,对于原始类型:除了null都可正确判断。
但对引用数据类型,除函数外,皆为object。
这样,采用typeof未免有些不合适。
我们想到了 instanceof——基于原型链的查询

var str='hello!';
str instanceof String   // false
const Person=function(){}
const p1=new Person()
p1 instanceof Person   // true

它当然也能判断基本数据类型:

class PrimitiveNum{
	static [Symbol.hasInstance](x){
		return typeof x==='number'
	}
}
console.log(111 instanceof PrimitiveNum)   // true

其实,我们就是通过Symbol将原有的instanceof重新定义成了typeof,这是自定义instanceof行为的一种方式。

玩个刺激的,

手动实现instanceof

我想到了 基于原型链的向上查找

function myInstanceof(left,right){
	//基本数据类型直接返回false
	if(typeof left !== 'object' || left === null) return false;
	//利用Object的自带方法拿到参数的原型对象
	let proto=Object.getPrototypeOf(left);
	while(true){
		if(proto==null) return false;   //参数的原型可能为null
		if(proto==right.prototype) return true;
		proto=Object.getPrototypeOf(proto);   //若上面不符,取自己的“原型对象”,继续向下走
	}
}

测试一下:

console.log(myInstanceof("111",String));   // false
console.log(myInstanceof(new String("111"),String));   // true

有趣的是,《深入浅出ES6》也对此有一个示例:(ES5模拟默认参数,通过typeof检查参数类型)

function makeRequest(url,timeout,callback){
	timeout=(typeof timeout !== "undefined") ? timeout : 2000;
	callback=(typeof callback !== "undefined") ? callback : function(){};
	//其余实现
}

运用:instanceof左操作数是一个类,右操作数是标识对象的类,如果左侧对象是右侧类的实例,则返回true
所以,一般用typeof判断基本类型,其余的再用instanceof判断

Object.is和===

作为 ES6的新增方法Object.is()Object.assign() 在ES里掀起了“简洁便利之风”。
我们着重说下Object.is()方法:

《深入浅出ES6》中提到:当你想在JavaScript中比较两个值时,可能习惯于使用相等运算符(= = )或全等运算符( = = =),许多开发者更喜欢后者,从而避免在比较时触发强制类型转换的行为。

但是,全等运算符也不一定准确啊:
+0和-0在JavaScript引擎中被表示为两个完全不同的实体,而全等运算符却将其归为一类;
NaN===NaN的返回值应该为true,但在JavaScript中也需要使用isNaN()来表示。

ES6引入了Object.is()方法来弥补全等运算符的不准确运算:

console.log(+0 == -0);   // true
console.log(+0 === -0);   // false
console.log(Object.is(+0,-0));   // false

console.log(NaN == NaN);   // false
console.log(NaN === NaN);   // false
console.log(Object.is(NaN,NaN));   // true

console.log(5 == "5");   // true
console.log(5 === "5");   // false
console.log(Object.is(5,"5"));   // false

猜你喜欢

转载自blog.csdn.net/qq_43624878/article/details/102669091