数据类型
基本类型:Undefined
、Null
、Boolean
、Number
、String
、Symbol
(ES6新增)
引用类型:Object
、Array
、Function
遍历操作(数组、对象)
for
- 十分常见,主要是用在数组中和一些dom操作中while
- 先判断再执行do while
- 先执行再判断for in
- 一般用于遍历对象,也可以遍历数组for of
-ES6
新增,遍历所有数据结构的统一方法。不仅可以用来遍历数组,还可以遍历字符串,以及ES6中的Map,Set。相关的方法:keys()
键名集合、values()
键值集合、entries()
键值对结合
跳出循环的方式
break
- 跳出当前循环continue
- 跳出本次循环 继续下次循环
字符串常用方法
查找:charAt
指定位置的字符、indexOf
指定字符的位置、lastIndexOf
从后往前找
截取:substr
按个数截取、substring
按位置截取
字大小写转换:toUpperCase
转换成大写、toLowerCase
转换成小写
分割:split
将字符串分割成数组
拼接:concat
将多个字符串拼接成一个字符串
替换:replace
把第一个参数拿到字符串中去搜索,匹配上了就用第二个参数去替换
搜索:search
匹配子字符串或正则是否在字符串中, 匹配上就返回具体的位置, 否则返回-1
匹配:match
匹配上就返回内容,匹配不上就返回null
数组常用方法
查找:indexOf
指定元素的位置、lastIndexOf
从后往前找
截取:slice
指定位置的元素(按位置截取)
增加:unshift
前增、push
后增
删除:shift
前删、pop
后删
格式化:map
将结果作为新的数组返回,不改变原数组
反转:reverse
颠倒数组中元素的顺序
遍历:forEach
没有返回值,直接改变原数组
过滤:filter
将符合条件的元素作为一个新数组返回、every
假如所有元素都符合判断条件,则返回true,否则为false、some
假如存在元素符合判断条件,则返回true,假如都不符合则为false
排序:sort
直接改变原数组,参数必须是规定元素排序顺序的函数
拼接:concat
将两个或多个数组拼接成一个数组,不会改变现有数组,只会返回一个拼接后的新数组
转化为字符串:toString
元素之间通过逗号分隔、join
元素通过指定的分隔符分隔,默认使用逗号分隔
reduce
数组中所有元素调用传参函数,返回值为最后的结果,传入的参数必须是函数
splice
数组的万能方法,可以实现增删改,不仅会改变原数组,而且将删除的元素作为一个新数组返回
Object 常用方法
.keys
:返回一个由对象的键(key)组成的数组.create
:返回一个新对象,带着指定的原型对象和属性。.assign
:合并对象,浅拷贝
浅拷贝-深拷贝
一、浅拷贝
将源对象的属性拷贝一份,如果属性时基本类型值,直接拷贝基本类型值,如果属性是引用类型,则拷贝的是 该引用类型在堆中的地址 的指向
- 展开运算符
...
(es6新增) Object.assign()
concat
、slice(0)
(数组)
二、深拷贝
比浅拷贝能够更深层级的拷贝,它能够将拷贝过程中遇到的引用类型都新开辟一块地址拷贝对应的数据,这样就能避免子对象共享同一份内存的问题
-
JSON.parse(JSON.stringify())
JSON.stringify
将对象先转成字符串,再通过JSON.parse
将字符串转成对象
缺陷:
a、不能解决循环引用的问题
b、无法拷贝特殊对象,比如:Set
、Map
、Date
、RegExp
等
c、忽略掉值为undefined
以及函数表达式 -
深拷贝方法
- 自定义:根据自己需求封装,使用遍历、递归、判断,
- 第三方:使用第三方js工具库,比如 Lodash
this 指向
this
指向最终调用它的那个对象。this
的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定。
- 全局:严格模式下指向
undefined
,非严格模式下且在浏览器环境下指向window
- 上下文对象:
this
指向最后调用它的对象 - 改变this指向:
call
、apply
、bind
- 构造函数:
this
指向实例
new 操作符调用构造函数的整个过程
- 创建一个新的对象
- 将构造函数的
this
指向这个新对象 - 为这个对象添加属性、方法等
- 最终返回新对象
改变 this 指向 call、apply、bind
第一个参数都是this
的指向,且当第一个参数为null
、undefined
的时候,默认指向window
(在浏览器中)
call
:后面传入的是一个参数列表(逗号隔开)
apply
:第二个参数是函数接受的参数(以数组的形式传入)
bind
:后面传入的也是一个参数列表(逗号隔开,可以分多次传入)。不会立即执行,返回一个永久改变this指向的函数
闭包
闭包就是引用了其他函数作用域中变量的函数
优点:变量、方法私有化(避免全局变量污染)
缺点:闭包会增大内存的使用量,不能滥用,否则会影响网页的性能。在IE9中可能会导致内存泄露,但这个导致内存泄露是IE早期的BUG。闭包本身并不会导致内存泄露。
节流、防抖
一、防抖
事件回调函数在一段时间后才执行,如果在这段时间内再次调用,则重新计时,当预定的时间内没有再次调用,则执行事件回调函数。
/**
* @description: 触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间
* @param func 执行函数
* @param wait 延迟时间
* @param immediate 是否立即执行
*/
function debounce(func, wait = 2000, immediate = true) {
let timeout, context, args
return function() {
context = this
args = arguments
if (timeout) clearTimeout(timeout)
if (immediate) {
const callNow = !timeout
timeout = setTimeout(function() {
timeout = null
}, wait)
if (callNow) func.apply(context, args)
} else {
timeout = setTimeout(function() {
func.apply(context, args)
}, wait)
}
}
}
二、节流
事件回调函数在一段时间内连续触发,只会执行一次,到下次开始计时的时候,就会在下一个时间段内再执行一次。
/**
* @description: 在n秒事件连续触发,函数只能执行一次
* @param func 执行函数
* @param wait 延迟时间
* @param immediate 是否立即执行
*/
function throttle(func, wait = 2000, immediate = true) {
let timeout, context, args
return function() {
context = this
args = arguments
if (!timeout) {
if (immediate) {
func.apply(context, args)
timeout = setTimeout(function() {
timeout = null
}, wait)
} else {
timeout = setTimeout(function() {
timeout = null
func.apply(context, args)
}, wait)
}
}
}
}
作用域、作用域链
一、作用域:
代码中的某些特定部分中变量,函数和对象的可访问性,决定了代码区块中变量和其他资源的可见性
- 全局作用域:最外层函数和在最外层函数外面定义的变量、末定义直接赋值的变量、
window
对象的属性 - 函数作用域:函数内部的变量
- 块级作用域(es6新增):
let
、const
,所声明的变量在指定块的作用域外无法被访问。在一个函数内部、在一个代码块(由一对花括号包裹)内部
二、作用域链
就是作用域的嵌套行为。在当前作用域中无法查找到某个变量时,就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(全局作用域)为止。这样一条有序的列表,称为作用域链。
原型、原型链
一、原型
JS声明构造函数(用来实例化对象的函数)时,会在内存中创建一个对应的对象,这个对象就是原函数的原型。
构造函数默认有一个prototype
属性,prototype
的值指向函数的原型。同时原型中也有一个constructor
属性,constructor
的值指向原函数。
通过构造函数实例化出来的对象,并不具有prototype
属性,其默认有一个__proto__
属性,该属性指向构造函数的原型对象。
二、原型链
当在实例化的对象中访问一个属性时,首先会在该对象内部寻找,如找不到,则会向其__proto__
指向的原型中寻找,如仍找不到,则继续向上级原型中寻找,直至找到或Object.prototype
为止,这种链状过程即为原型链
声明变量 var、let、const 的区别
var
:函数作用域、有变量提升、可重复声明、可重复赋值
let
:块级作用域、无变量提升、不可重复声明、可重复赋值
const
(常量):块级作用域、无变量提升、不可重复声明、不可重复赋值、必需初始化赋值
异步编程 Promise,async、await
异步编程,处理异步操作,确认异步操作完成再执行后面的语句
Promise
三种状态:pending
等待,resolved
成功,rejected
失败
链式调用:链式写法本质上是一直往下传递一个新的Promise
,也就是说then在下一步接收的是上一步返回的Promise
.then
接受两个回调函数,第一个为成功回调,第二个(可选)为失败回调.catch
接受一个失败回调函数Promise.reject
返回一个状态为失败的Promise
对象Promise.resolve(result)
返回一个状态由给定result
决定(失败或者成功)的Promise
对象Promise.all
将多个Promise
实例,包装成一个新的Promise
实例,可以来统一控制输出结果
async、await
async
函数的返回值是一个 promise
对象
await
后是一个 promise
对象,它会"阻塞"后面的代码,直到这个 promise
对象有返回结果,如果是resolve
状态,值就是resolve
参数,如果是reject
状态,会将错误抛出,抛出的错误可以使用try catch
捕获
await
后如果不是一个promise
对象,那该表达式就是要等待的东西,还是相当于在 then
执行
箭头函数 => 需要注意的地方
- 箭头函数不能用于构造函数,意味这不能用
new
关键字去调用 - 箭头函数内部没有
arguments
对象 - 箭头函数没有自己的
this
,它内部的this
,并不是调用的时候指向对象,而是定义的时候指向对象。this
的指向是可变的,但是在箭头函数中,它是固定的
Symbol 类型
ES6
中新增的一种数据类型,属于基本数据类型。用来表示独一无二的值。Symbol
里面传入的字符串没有其他意义,只是用来描述的,进行区分。
注意:
- 不能使用
new
关键字调用 - 做类型转换的时候不能转换成数字,不能做运算
- 如果把
Symbol
用于对象的属性和方法,一定要用一个变量来存
Set、Map 数据结构
Set
类似于数组,是不包含重复值的列表
属性:size
长度
api: add()
增加一个元素、 delete()
删除一个元素、 has()
查看是否存在某个元素、clear()
清空
应用场景:数组去重
Map
是键与相对应的值的集合。“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键
属性:size
长度
api:set()
设置键值对、 get()
根据key获取value、 delete()
删除key、 has()
查看是否有key、 clear()
清空
应用场景:储存数据
ES5、ES6的继承
名称 | 描述 | 继承属性 | 继承方法 |
---|---|---|---|
ES5 | ES5 通过构造函数和原型prototype ,来实现继承 | 使用 call ,在子类构造函数中调用父类构造函数。function Child(params) { Parent.call(this,params) } | 创建父类原型的一个副本,把副本赋值给子类原型。 Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child |
ES6 | ES6 提供了类 class 语法糖,类 class 的继承是通过 extends 来实现。class Child extends Parent { } | 在子类的 constructor 函数中执行 super 函数。constructor(params) { super(params) } | 使用了 extends 后,子类已经实现了对父类方法的复用 |