We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
作者:Dmitri Pavlutin 译者:前端小智 来源:https://dmitripavlutin.com/javascript-type-checking-screwed/
JS 的动态类型有好有坏。好的一面,不必指明变量的类型。不好的是,咱们永远无法确定变量的类型。
typeof运算符可以确定 JS 中的6种类型:
typeof
6
typeof 10; // => 'number' typeof 'Hello'; // => 'string' typeof false; // => 'boolean' typeof { a: 1 }; // => 'object' typeof undefined; // => 'undefined' typeof Symbol(); // => 'symbol'
同样,instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
instanceof
prototype
class Cat { } const myCat = new Cat(); myCat instanceof Cat; // => true
但是typeof和instanceof的一些行为可能会令人混淆。防范于未然,咱们需要提前了解一些边缘情况。
typeof myObject === 'object'会告知myObject是否是一个对象类型。举个例子:
typeof myObject === 'object'
myObject
const person = { name: '前端小智' }; typeof person; // => 'object'
typeof person是'object',因为person是一个普通的 JS 对象。
typeof person
'object'
person
在某场景下,变量值可能需要指定为 null,下面是一些场景:
null
可以使用null来跳过指示配置对象
使用null初始化稍后要保存对象的变量
当函数由于某种原因无法构造对象时,返回null
例如,如果不存在正则表达式匹配项,则str.match(regExp)方法返回null:
str.match(regExp)
const message = 'Hello'; message.match(/Hi/); // => null
这里引出一个问题,可以使用typeof 来区分有值的对象和具有 null 值的对象吗?
let myObject = null; typeof myObject; // => 'object' myObject = { prop: 'Value' }; typeof myObject; // => 'object'
从上面可以看出,typeof 对象有值的对象和具有 null 值的对象,得到的结果都是'object'。
可以如下面方法来检测变量是否有对象且不是null:
function isObject(value) { return typeof value === 'object' && value !== null; } isObject({}); // => true isObject(null); // => false
除了检查value是否为object: typeof value === 'object'之外,还需要明确地验证null: value !== null。
value
object
typeof value === 'object'
value !== null
如果试图检测一个变量是否包含一个数组,常见的错误就是使用typeof操作符:
const colors = ['white', 'blue', 'red']; typeof colors; // => 'object'
检测数组的正确方法是使用Array.isArray():
Array.isArray()
const colors = ['white', 'blue', 'red']; const hero = { name: 'Batman' }; Array.isArray(colors); // => true Array.isArray(hero); // => false
Array.isArray(colors)返回一个布尔值true,表示colors是一个数组。
Array.isArray(colors)
true
colors
JS中的undefined是一个特殊值,表示未初始化的变量。
undefined
如果试图访问未初始化的变量、不存在的对象属性,则获取到的值为 undefined :
let city; let hero = { name: '前端小智', villain: false }; city; // => undefined hero.age; // => undefined
访问未初始化的变量 city 和不存在的属性hero.age的结果为undefined。
city
hero.age
要检查属性是否存在,可以在条件中使用object[propName],这种遇到值为虚值或者undefined是不可靠的:
object[propName]
function getProp(object, propName, def) { // 错误方式 if (!object[propName]) { return def; } return object[propName]; } const hero = { name: '前端小智', villain: false }; getProp(hero, 'villain', true); // => true hero.villain; // => false
如果对象中不存在propName,则object [propName]的值为undefined。 if (!object[propName]) { return def }保护缺少的属性。
propName
object [propName]
if (!object[propName]) { return def }
hero.villain属性存在且值为false。 但是,该函数在访问villan值时错误地返回true:getProp(hero, 'villain', true)
hero.villain
false
villan
getProp(hero, 'villain', true)
undefined是一个虚值,同样false、0和''和null。
0
''
不要使用虚值作为类型检查,而是要明确验证属性是否存在于对象中:
typeof object[propName] === 'undefined'
propName in object
object.hasOwnProperty(propName)
接着,咱们来改进getProp()函数:
getProp()
function getProp(object, propName, def) { // Better if (!(propName in object)) { return def; } return object[propName]; } const hero = { name: '前端小智', villain: false }; getProp(hero, 'villain', true); // => false hero.villain; // => false
if (!(propName in object)) { ... }条件正确确定属性是否存在。
if (!(propName in object)) { ... }
我认为最好避免使用逻辑运算符||作为默情况,这个容易打断阅读的流程:
||
const hero = { name: '前端小智', villain: false }; const name = hero.name || 'Unknown'; name; // => '前端小智' hero.name; // => '前端小智' // 不好方式 const villain = hero.villain || true; villain; // => true hero.villain; // => false
hero 对象存在属性villain,值为 false,但是表达式hero.villain || true结果为true。
hero
villain
hero.villain || true
逻辑操作符||用作访问属性的默认情况,当属性存在且具有虚值时,该操作符无法正确工作。
若要在属性不存在时默认设置,更好的选择是使用新的**双问号(??)**操作符,
const hero = { name: '前端小智', villan: false }; // 好的方式 const villain = hero.villain ?? true; villain; // => false hero.villain; // => false
或使用解构赋值:
const hero = { name: '前端小智', villain: false }; // Good const { villain = true } = hero; villain; // => false hero.villain; // => false
整数,浮点数,特殊数字(例如Infinity,NaN)的类型均为数字。
Infinity
NaN
typeof 10; // => 'number' typeof 1.5; // => 'number' typeof NaN; // => 'number' typeof Infinity; // => 'number'
NaN是在无法创建数字时创建的特殊数值。NaN是not a number的缩写。
not a number
在下列情况下不能创建数字:
Number('oops'); // => NaN 5 * undefined; // => NaN Math.sqrt(-1); // => NaN NaN + 10; // => NaN
由于NaN,意味着对数字的操作失败,因此对数字有效性的检查需要额外的步骤。
下面的isValidNumber()函数也可以防止NaN导致的错误:
isValidNumber()
function isValidNumber(value) { // Good return typeof value === 'number' && !isNaN(value); } isValidNumber(Number('Z99')); // => false isValidNumber(5 * undefined); // => false isValidNumber(undefined); // => false isValidNumber(Number('99')); // => true isValidNumber(5 + 10); // => true
除了typeof value === 'number'之外,还多验证!isNaN(value)确保万无一失。
typeof value === 'number'
!isNaN(value)
JS 中的每个对象都引用一个特殊的函数:对象的构造函数。
object instanceof Constructor是用于检查对象的构造函数的运算符:
object instanceof Constructor
const object = {}; object instanceof Object; // => true const array = [1, 2]; array instanceof Array; // => true const promise = new Promise(resolve => resolve('OK')); promise instanceof Promise; // => true
现在,咱们定义一个父类Pet和它的子类Cat:
Pet
Cat
class Pet { constructor(name) { this.name; } } class Cat extends Pet { sound = 'Meow'; } const myCat = new Cat('Scratchy');
现在,尝试确定myCat的实例
myCat
myCat instanceof Cat; // => true myCat instanceof Pet; // => true myCat instanceof Object; // => true
instanceof运算符表示myCat是Cat,Pet甚至Object的实例。
Object
instanceof操作符通过整个原型链搜索对象的构造函数。要准确地检测创建对象的构造函数,需要检测 constructor 属性
constructor
myCat.constructor === Cat; // => true myCat.constructor === Pet; // => false myCat.constructor === Object; // => false
只有myCat.constructor === Cat的计算结果为true,表示 Cat 是 myCat实例的构造函数。
myCat.constructor === Cat
运算符typeof和instanceof 用于类型检查。 它们尽管易于使用,但需要注意一些特殊情况。
需要注意的是:typeof null等于'object'。 要确定变量是否包含非null对象,需要显示指明null:
typeof null
typeof myObject === 'object' && myObject !== null
检查变量是否包含数组的最佳方法是使用Array.isArray(variable)内置函数。
Array.isArray(variable)
因为undefined是虚值的,所以我们经常直接在条件句中使用它,但这种做法容易出错。更好的选择是使用prop in object来验证属性是否存在。
prop in object
使用双问号操作系符号object.prop ?? def 或者 { prop = def } = object 来访问可能丢失的属性。
object.prop ?? def
{ prop = def } = object
NaN是一个类型为number的特殊值,它是由对数字的无效操作创建的。为了确保变量有正确的数字,最好使用更详细的验证:!isNaN(number) && typeof number === 'number'。
number
!isNaN(number) && typeof number === 'number'
最后,请记住instanceof通过prototype链搜索实例的构造函数。如果不知道这一点,那么如果使用父类验证子类实例,可能会得到错误的结果。
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://dmitripavlutin.com/javascript-type-checking-screwed/
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
https://github.com/qq449245884/xiaozhi
我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,即可看到福利,你懂的。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
JS 的动态类型有好有坏。好的一面,不必指明变量的类型。不好的是,咱们永远无法确定变量的类型。
typeof
运算符可以确定 JS 中的6
种类型:同样,
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上。但是
typeof
和instanceof
的一些行为可能会令人混淆。防范于未然,咱们需要提前了解一些边缘情况。1. typeof null
typeof myObject === 'object'
会告知myObject
是否是一个对象类型。举个例子:typeof person
是'object'
,因为person
是一个普通的 JS 对象。在某场景下,变量值可能需要指定为
null
,下面是一些场景:可以使用
null
来跳过指示配置对象使用
null
初始化稍后要保存对象的变量当函数由于某种原因无法构造对象时,返回
null
例如,如果不存在正则表达式匹配项,则
str.match(regExp)
方法返回null
:这里引出一个问题,可以使用typeof 来区分有值的对象和具有
null
值的对象吗?从上面可以看出,
typeof
对象有值的对象和具有null
值的对象,得到的结果都是'object'。可以如下面方法来检测变量是否有对象且不是
null
:除了检查
value
是否为object
:typeof value === 'object'
之外,还需要明确地验证null
:value !== null
。2. typeof array
如果试图检测一个变量是否包含一个数组,常见的错误就是使用
typeof
操作符:检测数组的正确方法是使用
Array.isArray()
:Array.isArray(colors)
返回一个布尔值true
,表示colors
是一个数组。3.虚值类型检查
JS中的
undefined
是一个特殊值,表示未初始化的变量。如果试图访问未初始化的变量、不存在的对象属性,则获取到的值为
undefined
:访问未初始化的变量
city
和不存在的属性hero.age
的结果为undefined
。要检查属性是否存在,可以在条件中使用
object[propName]
,这种遇到值为虚值或者undefined
是不可靠的:如果对象中不存在
propName
,则object [propName]
的值为undefined
。if (!object[propName]) { return def }
保护缺少的属性。hero.villain
属性存在且值为false
。 但是,该函数在访问villan
值时错误地返回true
:getProp(hero, 'villain', true)
undefined
是一个虚值,同样false
、0
和''
和null
。不要使用虚值作为类型检查,而是要明确验证属性是否存在于对象中:
typeof object[propName] === 'undefined'
propName in object
object.hasOwnProperty(propName)
接着,咱们来改进
getProp()
函数:if (!(propName in object)) { ... }
条件正确确定属性是否存在。逻辑运算符
我认为最好避免使用逻辑运算符
||
作为默情况,这个容易打断阅读的流程:hero
对象存在属性villain
,值为false
,但是表达式hero.villain || true
结果为true
。逻辑操作符
||
用作访问属性的默认情况,当属性存在且具有虚值时,该操作符无法正确工作。若要在属性不存在时默认设置,更好的选择是使用新的**双问号(??)**操作符,
或使用解构赋值:
4. typeof NaN
整数,浮点数,特殊数字(例如
Infinity
,NaN
)的类型均为数字。NaN
是在无法创建数字时创建的特殊数值。NaN
是not a number
的缩写。在下列情况下不能创建数字:
由于
NaN
,意味着对数字的操作失败,因此对数字有效性的检查需要额外的步骤。下面的
isValidNumber()
函数也可以防止NaN
导致的错误:除了
typeof value === 'number'
之外,还多验证!isNaN(value)
确保万无一失。5.instanceof 和原型链
JS 中的每个对象都引用一个特殊的函数:对象的构造函数。
object instanceof Constructor
是用于检查对象的构造函数的运算符:现在,咱们定义一个父类
Pet
和它的子类Cat
:现在,尝试确定
myCat
的实例instanceof
运算符表示myCat
是Cat
,Pet
甚至Object
的实例。instanceof
操作符通过整个原型链搜索对象的构造函数。要准确地检测创建对象的构造函数,需要检测constructor
属性只有
myCat.constructor === Cat
的计算结果为true
,表示Cat
是myCat
实例的构造函数。6. 总结
运算符
typeof
和instanceof
用于类型检查。 它们尽管易于使用,但需要注意一些特殊情况。需要注意的是:
typeof null
等于'object'
。 要确定变量是否包含非null
对象,需要显示指明null
:检查变量是否包含数组的最佳方法是使用
Array.isArray(variable)
内置函数。因为
undefined
是虚值的,所以我们经常直接在条件句中使用它,但这种做法容易出错。更好的选择是使用prop in object
来验证属性是否存在。使用双问号操作系符号
object.prop ?? def
或者{ prop = def } = object
来访问可能丢失的属性。NaN
是一个类型为number
的特殊值,它是由对数字的无效操作创建的。为了确保变量有正确的数字,最好使用更详细的验证:!isNaN(number) && typeof number === 'number'
。最后,请记住
instanceof
通过prototype
链搜索实例的构造函数。如果不知道这一点,那么如果使用父类验证子类实例,可能会得到错误的结果。代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://dmitripavlutin.com/javascript-type-checking-screwed/
交流
干货系列文章汇总如下,觉得不错点个Star,欢迎 加群 互相学习。
我是小智,公众号「大迁世界」作者,对前端技术保持学习爱好者。我会经常分享自己所学所看的干货,在进阶的路上,共勉!
关注公众号,后台回复福利,即可看到福利,你懂的。
The text was updated successfully, but these errors were encountered: