JS 变量类型
JS 中有 6 种原始值,分别是:
- boolean
- number
- string
- undefined
- symbol
- null
- object
引用类型:
- 对象
- 数组
- 函数
JS 中使用 typeof 能得到哪些类型?
其中一个奇怪的 null,虽然是基本变量,但是因为设计的时候null
是全 0,而对象是000
开头,所以有这个误判。
- boolean
- number
- string
- undefined
- symbol
- object
- function
- bigint
instanceof 能正确判断对象的原理是什么?
判断一个对象与构造函数是否在一个原型链上
function instanceofs(a, b) {
if (a == null) return false
if (a.__proto__ == b.prototype) {
return true
}
return instanceofs(a.__proto__, b)
}
instanceofs(p1, Person)
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
实现一个类型判断函数
- 判断 null
- 判断基础类型
- 使用
Object.prototype.toString.call(target)
来判断引用类型
注意: 一定是使用call
来调用,不然是判断的 Object.prototype 的类型
之所以要先判断是否为基本类型是因为:虽然Object.prototype.toString.call()
能判断出某值是:number/string/boolean,但是其实在包装的时候是把他们先转成了对象然后再判断类型的。 但是 JS 中包装类型和原始类型还是有差别的,因为对一个包装类型来说,typeof 的值是 object
/**
* 类型判断
*/
function getType(target) {
//先处理最特殊的Null
if (target === null) {
return 'null'
}
//判断是不是基础类型
const typeOfT = typeof target
if (typeOfT !== 'object') {
return typeOfT
}
//肯定是引用类型了
const template = {
'[object Object]': 'object',
'[object Array]': 'array',
// 一些包装类型
'[object String]': 'object - string',
'[object Number]': 'object - number',
'[object Boolean]': 'object - boolean',
}
const typeStr = Object.prototype.toString.call(target)
return template[typeStr]
}
"a common string"为什么会有 length 属性
通过字面量的方式创建:var a = 'string';,这时它就是基本类型值; 通过构造函数的方式创建:var a = new String('string');这时它是对象类型。
基本类型是没有属性和方法的,但仍然可以使用对象才有的属性方法。 这时因为在对基本类型使用属性方法的时候,后台会隐式的创建这个基本类型的对象,之后再销毁这个对象
如何判断一个数据是不是 Array
Array.isArray(obj)
- ECMAScript 5 种的函数,当使用 ie8 的时候就会出现问题。
obj instanceof Array
- 当用来检测在不同的 window 或 iframe 里构造的数组时会失败。这是因为每一个 iframe 都有它自己的执行环境,彼此之间并不共享原型链,所以此时的判断一个对象是否为数组就会失败。此时我们有一个更好的方式去判断一个对象是否为数组。
Object.prototype.toString.call(obj) == '[object Array]'
- 这个方法比较靠谱
obj.constructor === Array
- constructor 属性返回对创建此对象的函数的引用
undefined 可被赋值
在 ES3 中(Firefox4 之前),window.undefined 就是一个普通的属性,你完全可以把它的值改变成为任意的真值,但在 ES5 中((Firefox4 之后),window.undefined 成了一个不可写,不可配置的数据属性,它的值永远是 undefined。
var undefined = 1
alert(undefined) // chrome: undefined, ie8: 1
不管是标准浏览器,还是老的 IE 浏览器,在函数内部 undefined 可作为局部变量重新赋值
function fn() {
var undefined = 100
alert(undefined) //chrome: 100, ie8: 100
}
fn()
有时候我们需要判断一个变量是不是 undefined,会这样用
if (str === undefined) {
console.log('I am empty')
}
但假如 str 这个变量没声明就会出现报错,用下面的方式会更好一些
if (typeof str === 'undefined') {
console.log('I am better')
}
有时候我们会看到这种写法
if (str === void 0) {
console.log('I am real undefind')
}
那是因为 「void 0」的执行结果永远是「undefined」, 即使在某些老旧浏览器 或者在某个函数中 undefined 被重新赋值,我们仍然可以通过void 0
得到真正的 undefined
。