1、数据类型
包括:基本数据类型(简单数据类型)、引用数据类型(复杂数据类型)
- 基本数据类型
Number(数字)、String(字符串)、Boolean(布尔值)、null(空)、undefined(未定义)、Symbol(符号)、BigInt - 引用数据类型
Object(对象)、Function(函数)、Array(数组)、正则等
基本类型和引用类型的存储区别:
- 基本数据类型存储在栈中,所占空间小,大小固定,属于被频繁使用的数据。
- 引用数据类型存储在堆内存中,占据空间大,大小不固定;引用数据类型在战中存储了指针,该指针指向堆中该实体的起始地址,当解析器寻找引用值时,会检索到在栈中的地址,取得地址后在队中获得实体。
2、JS中数据类型的检测方法
三种方法:typeof、instanceof、Object.prototype.toString.call()
- typeof
//示例
console.log(typeof 1);//number
console.log(typeof []);//object
console.log(typeof {});//object
console.log(typeof null);//object
优点:能够快速区分基本数据类型(除了null)
缺点:不能区分Object、Array、Null,他们都会返回object
- instanceof
console.log(1 instanceof Number);//false
console.log(true instanceof Boolean);//false
console.log([] instanceof Array);//true
优点:能够区分Array、Object、Function,适合用于判断自定义的类实例对象
缺点:不能区分Number,Boolean,String基本数据类型
- Object.prototype.toString.call()
var toString = Object.prototype.toString;
console.log(toString.call(1));//[object Number]
console.log(toString.call('str'));//[object String]
console.log(toString.call({}));//[object Object]
console.log(toString.call(function(){}));//[object Function]
优点:可以精准判断数据类型
缺点:写法繁琐不容易记
3、let、const、var的区别
-
变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined。
let、const不存在变量提升,即他们所声明的变量一定要在声明后使用,否则会报错。 -
暂时性死区
(暂时性死区就是指在声明变量之前,该变量都是不可以使用的)
所以:let、const声明的变量是有暂时性死区的,var声明的变量没有。 -
块级作用域
var不存在块级作用域。
let、const存在块级作用域。
注:块级作用域就是在{ }里面的 -
全局变量
var生命的变量是全局变量,并且生命的变量会被添加到全局对象的属性当中。
let和const不会。 -
重复声明
var 允许重复声明,后声明的同名变量会覆盖之前声明的变量。
let、const在同一作用域中不允许重复声明。 -
初始值
在声明变量的时候,var、let可以不设置初始值,但是const必须设置初始值。 -
修改声明变量
var、let可以修改变量的值。
const不可以,const声明一个只读的常量,一旦声明常量的之就不能修改。
4、原型和原型链
原型:每一个对象都与另一个对象相关联,那个关联的对象就称为原型。
例如:函数Person有一个属性prototype,指向一个对象,对于普通函数来说没多意义,对于构造函数就有作用了,当使用new操作符时,会把Person.prototype(原型对象)赋值给实例的 proto(原型实例)属性。
JS有一个原型查找机制,把原来定义在实例上的方法,放到原型对象上去,通过构造函数的new操作,会把原型对象赋值给实例的__proto__属性,那么当使用返回的实例去调用某一个方法的时候,如果实例本身上没有,就去自动去实例的__proto__上去查找,这样达到方法的复用,减少内存开销。
原型链:每一个对象,都有一个原型对象与之关联,这个原型对象它也是一个普通对象,这个普通对象也有自己的原型对象,这样层层递进,就形成了一个链条,这个链条就是原型链。通过原型链可以实现JS的继承,把父类的原型对象赋值给子类的原型,这样子类实例就可以访问父类原型上的方法了。
举例说明:
function Person(){ }
var zhangsan = new Person();
上述代码的原型链如下图:
可以分析一下:
- 构造函数
Person
存在原型对象Person.prototype
. - 构造函数生成实例对象
zhangsan
的__proto__
指向构造函数Person原型对象(prototype). Person.prototype.__proto__
指向Object.prototype
,因为 Person.prototype 是个对象,默认是由 Object函数作为类创建的.Person.__proto__
指向Function.prototype
,因为 Person 是个函数对象,默认由 Function 作为类创建.
总结:
- 一切对象都是继承自
Object
对象,Object对象直接继承跟对象null - 一切函数对象(包括Object对象)都继承自Function
- Function对象的
__proto__
会指向自己的原型对象,最终还是继承Object对象
5、== 和 ===的区别
== 操作符:如果相比较的两个值相等,则返回true,否则false
=== 操作符:相比较的两个值相等且数据类型相同,则返回true,否则返回false
注:==操作符在比较中会先进行类型转换,再比较值是否相等; ===操作符不会进行类型的转换
==操作符比较所遵循的规则:
- 两个都为简单类型,字符串和布尔值都会转换成数值,再比较
- 简单类型与引用类型比较,对象转化成其原始类型的值(使用
valueOf()
方法),再比较 - 两个都为引用类型,则比较它们是否指向同一个对象
- null 和 undefined 相等
- 存在 NaN 则返回 false
除了在比较对象属性为null或者undefined的情况下,我们可以使用相等操作符(==),其他情况建议一律使用全等操作符 ( === )
今天就先准备这么多,明天继续,加油!!