闭包是指能够访问另一个函数作用域中的变量的一个函数。 在js中,只有函数内部的子函数才能访问局部变量, 所以闭包可以理解成 “定义在一个函数内部的函数”。
将内部的函数返到外部去,让外部函数可以访问到内部函数的变量和方法
延长外部函数局部变量的生命周期
优点也是缺点,本应被销毁的变量,因为闭包的原因没有被销毁,长期存在的话,容易造成内存泄漏
改变函数内部 this 的指向
1、call 和 apply 会调用函数,而 bind 不会调用
2、call 和 bind 的参数是 参数列表逐个传入,而 apply 的参数必须为数组形式
1、call 经常做继承
2、apply 经常跟数组有关系,比如借用 Math 对象对数组进行处理
3、bind 不调用函数,但是想改变 this 的指向,比如改变定时器内部的 this 指向
1、原始值大小固定,保存在栈内存中从一个变量到另一个变量复制原始值,会创建该值得第二个副本
2、引用值是对象,存储在堆内存中包含引用值的变量实际上只包含指向相应对象的一个指针,而不是对象本身
3、从一个变量到另一个变量复制引用值,只会复制指针,因此结果是两个变量都指向同一个对象
4、typeof操作费可以确定值的原始类型,instanceof操作符用于确保值得引用类型
任何变量都存在于某个执行上下文中(也称为作用域)。这个上下文(作用域)决定了变量的生命周期,以及它们可以访问代码的哪些部分。
1、执行上下文分为:全局上下文、 函数上下文、 块级上下文
2、代码执行流每进入一个新上下文,都会创建一个作用域链,用于搜索变量和函数
3、函数或块的局部上下文不仅可以访问自己作用域内的变量,也可以访问任何包含上下文乃至全局上下文的变量
4、全局上下文只能访问全局上下文中的变量和函数,不能直接访问局部上下文中的任何数据
5、每个函数都有一个作用域链,查找变量或方法时,会先从函数作用域逐层查找最后到全局作用域查找,这些作用域的集合称为作用域链。
**垃圾回收基本思路:**确定那个变量不会再使用,然后释放它占用的内存。这个过程是周期性的,即垃圾回收程序每隔一定时间就会自动运行。
JavaScript是使用垃圾回收的编程语言,开发者不需要操心内存分配和回收。
1、离开作用域的值会被自动标记为可回收,然后在垃圾回收期间被删除
2、主流的垃圾回收算法是标记算法,即先给当前不使用的值加上标记,再回来回收它们的内存
3、引用计数是另一种垃圾回收策略,需要记录值被引用了多少次。JavaScript引擎不再使用这种算法,但某些旧版本的IE仍然会受这种算法的影响,原因是JavaScript会访问非原生JavaScript对象(如DOM对象)。
4、引用计数在代码中循环引用时会出现问题
5、解除变量的引用不仅可以消除循环引用,而且对垃圾回收也有帮助。为促进内存回收,全局对象、全局对象的属性和循环引用都应该在不需要时解除引用。
ECMA-262把原型链定义为ECMAScript的主要继承方式。其基本思想就是通过原型继承多个引用类型的属性和方法。
每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数,这样就在实例和原型之间构造了一条原型链。
无用的内存还在占用,得不到释放和归还,比较严重的时候,无用的内存还会增加,从而导致整个系统卡顿,甚至崩溃。
如果拷贝的是基本数据类型相当于直接拷贝它的值,修改值互不影响
如果拷贝的是引用数据类型,拷贝的就是指向堆内存里面这个对象的内存地址,如果修改了其中一个对象的数据,那么另一个对象也会受到影响,因为内存地址指向堆里面同一块内存
常用 es6 0bject.assign() 实现
深拷贝是将一个对象完整的独立拷贝一份出来,然后在堆内存中开辟一块新的内存块存储,所以不会互相影响
常用 es6扩展运算符 递归 Array.concat() 实现
或者转为字符串再转为数组
在es5中构造函数其实就是在定义一个类,可以实例化对象,es6中class其实是构造函数的语法糖。但还是有点区别的:
同步任务是指在主线程上排队执行的任务,
只有前一个任务执行完毕,才能继续执行下一个任务。
异步任务指的是,不进入主线程、而进入"任务队列"的任务,只有等主线程任务执行完毕,"任务队列"的任务才会进入主线程执行。
异步任务分为 宏任务 和 微任务
typeof 用来检测数据类型的运算符
检测的不管是数组还是正则都返回的是"object",所以typeof不能判断一个值是否为数组
instanceof/constructor。检测某一个实例是否属于某一个类使用instanceof/constructor可以检测数组和正则
用instanceof检测的时候,只要当前的这个类在实例的原型链上(可以通过原型链__proto__找到它),检测出来的结果都是true。
基本数据类型的值是不能用instanceof来检测的
在类的原型继承中,instanceof检测出来的结果其实是不准确的
Object.prototype.toString.call(value) ->找到Object原型上的toString方法,让方法执行,并且让方法中的this变为value(value->就是我们要检测数据类型的值)。检测的类型比较多,也比较精准。
concat() 连接两个或更多的数组,并返回结果。join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。pop() 删除并返回数组的最后一个元素。 shift() 删除并返回数组的第一个元素push() 向数组的末尾添加一个或更多元素,并返回新的长度。unshift() 向数组的开头添加一个或更多元素,并返回新的长度。reverse() 颠倒数组中元素的顺序。slice() 从某个已有的数组返回选定的元素sort() 对数组的元素进行排序splice() 删除元素,并向数组添加新元素。toSource() 返回该对象的源代码。toString() 把数组转换为字符串,并返回结果。toLocaleString() 把数组转换为本地数组,并返回结果。valueOf() 返回数组对象的原始值
let、const
解构赋值
模板字符串
箭头函数
函数默认值
promise
set、map结构
class类
symbol
Iterator 和 for…of 循环.
数值的扩展方法
数组的扩展方法
正则的扩展方法
对象的扩展方法
var 和 let/const 都是 JavaScript 中声明变量的关键字,但是它们在作用域和变量提升方面有一些不同。
var 声明的变量存在变量提升,在代码块执行前就已经存在,并且值为 undefined。
let 和 const 声明的变量不存在变量提升,在代码块执行前不存在,并且在代码块内部作用域内有效。
let 声明的变量可以被重新赋值,而 const 声明的变量不能被重新赋值。
const保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。对于基本类型的数据(数值、字符串、布尔值),其值就保存在变量指向的那个内存地址,因此等同于常量。
但对于引用类型的数据(主要是对象和数组)来说,变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了。
箭头函数是ES6中的提出来的,它没有prototype,也没有自己的this指向,更不可以使用arguments参数,所以不能New一个箭头函数。
(1)用了箭头函数,this就不是指向window,而是父级(指向是可变的)
(2)不能够使用arguments对象
(3)不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数
上一篇:多版本并发控制MVCC