JS 数据类型
8种基本数据类型(值类型): String、Number、Boolean、Null、undefined、BigInt、Symbol
- Symbol:代表独一无二的值,最大的用法是用来定义对象的唯一属性名。
- BigInt:可以表示任意大小的整数。
引用数据类型: Object、Array、Function
值类型和引用类型的区别: 值类型存在栈里,引用类型存在堆里
typeof 对类型的判断:
- 可以判断所有值类型和 Function
- Object、Array、null 都会被识别为 Object 类型
判断数组的方法:
- isArray
- instanceof Array
- arr.constructor === Array
=== 和 ==:
- === :全等
- == 会进行类型转换尽量使两边相等,一般只有在判断 null 和 undefined 时才会使用 ==
- 在进行计算时数据需要先转换为二进制,因此可能会丢失精度
手写深拷贝:
function deepClone(obj) {
if(obj === null || typeof obj !== Object) return obj
let newObj = obj.isArray ? []:{}
for(let key in obj){
// 确保key不是原型的属性
if(obj.hasOwnProperty(key)){
newObj[key] = deepClone(obj[key])
}
}
return newObj;
}
原型和原型链
原型:
- 每个构造函数都有一个显式原型 prototype
- 每个实例对象都有一个隐式原型 _ _ proto _ _
- 实例对象的_ _ proto _ _指向其构造函数的 prototype
- 每个构造函数的 prototype 有一个_ _ proto _ _指向其父类的 prototype
- 构造函数的 prototype 的 constructor 指向构造函数本身
原型链:
- 实例调用方法时,先在自身寻找
- 找不到就通过实例的_ _ proto _ _去其构造函数的prototype上寻找
- 找不到再通过构造函数prototype的_ _ proto _ _去其构造函数的prototype上寻找
- 可以通过对象的 hasOwnProperty 方法判断要调用的方法是否是实例对象自身的方法
new的实现过程:
- 先创建一个空对象
- 使该对象的_ _ proto _ _指向构造函数的prototype
- 让函数的this指向该对象,并执行构造函数代码为对象添加属性
- 返回值:如果构造函数的返回值是一个对象,直接返回这个对象,否则返回新创建的对象
instanceof 的作用:
- 用于判断对象是否是某个构造函数的实例,只要在原型链上就为 true
- 可以用于判断一个对象是否为数组: obj instanceof Array
作用域和闭包
作用域类型:全局作用域、函数作用域、块级作用域(es6新增)
作用域链:
- 如果当前作用域内使用了未定义的变量,则该变量为自由变量
- 从当前函数定义位置向外逐层寻找该变量的定义
- 如果到到全局作用域仍未找到则该变量为 undefine
闭包: 函数调用的位置跟函数定义的位置不一样
- 形成条件:函数作为参数或返回值
- 实质:从函数定义位置向外寻找自由变量
变量提升:
- JS预解析把所有 var 变量声明和 函数声明提升到当前作用域最前面
- 变量提升只提升声明,不提升赋值(初始化)
- 函数表达式声明属于变量提升
- 函数提升只提升声明,不提升调用
改变函数this指向:
- call:函数会立即执行
- apply:函数会立即执行,接收的函数参数为数组形式
- bind:接收的函数参数为数组形式,函数不会立即执行,而是返回改绑后的新函数,便于稍后调用
手写bind实现:
Function.prototypr.myBind = function(obj) {
var self = this //原函数this
var args1 = Array.protptype.slice.call(arguments, 1) //arguments是伪数组
var fun1 = function() {
var args2 = Array.prototype.slice.call(arguments)
self.apply(context, args.concat(newArgs)) //合并两args
}
}
数组和字符串常用方法:
for...in 和 for...of :
- for...in:用于遍历对象或数组的 key,主要用于对象
- for...of:用于遍历数组项 item
手写数组去重:
let newArr = [Array.from(new Set(arr))] //利用Set数据结构
手写数组扁平化:
//第一种
arr.flat()
//第二种
function flatten(arr) {
return arr.reduce((flatArr, item)=>{
Array.isArray(item)? flatArr.push(...flatten(item)) : flatArr.push(item)
return flatArr
}, [])
}