1、变量
.用于存放数据,存放的数据可以改变
.本质:变量本身也是数据,也需要在内存中占用空间,保存在内存的栈结构分区中。
2、常量
.用来保存数据,保存的数据不可以修改
.本质:常量本身也是数据。需要占用空间,保存在栈。
3、基本数据类型特点
.一旦定义了值是不会发生改变的。
4、typeof
.检测数据类型,只能检测到String Number Boolean Undefined Function Object
.假如用typeof检测,数组和null 返回值都是Object
5、instanceof
.用来判断A是否是B的实例 ,返回值是布尔值。
6、js内存结构
.js其实只有堆内存结构,只是在使用的堆内存结构中分区分为栈结构和堆结构。
.栈结构:全局变量,局部变量(空间较小)
.堆结构:对象(空间较大)
.一块内存包含两个数据:内部存储的数据和内存地址数据。
函数
7、函数
.函数对象和普通对象不同的是,函数对象有行为。
.为什么要设计函数?
——减少重复代码。
——函数功能点是明确的。复用
——减少命名污染
.定义函数方式
——函数声明式 function fun(){}
——函数表达式 var fun =function(){}
.函数调用方式
——直接调用 test();
——构造函数调用 new Arry();
——当方法调用 hello.test();
——call 和apply 强制绑定this,自动调用修改完this的函数
8、立即执行函数
.一开始我们就需要调用,而且调用完再也不用的函数。
9、函数分类
.普通函数
.构造函数
.立即执行函数
.回调函数
10、this
.既是关键字也是变量
.函数的this不是函数定义的时候决定的。
.函数this指向谁看如何调用当前的函数
.new fun() ;//
11、this指向分类
.函数自调用 --widow
.构造函数 --当前构造函数的实例对象
.对象.方法 --对象本身
.fun.call/apply(); 指定对象
12、回调函数
.程序员定义,但没直接调用,但它最终执行了(特定条件下)
原型
13、new操作符
(new干了什么?)
.创建一个空对象。
.将this 指向该空对象。
.执行函数
.将执行的结果返回
14、什么是原型对象
.每个函数都有一个prototype属性,该属性指向的是原型对象(显示原型对象)
.每个实例对象身上都有__ptoto__属性,该属性指向的也是原型对象(隐式原型对象)
.构造函数的显示原型 === 当前构造函数实例对象的隐式原型对象。
15、原型链
.查找对象的属性的时候先在自身找,如果自身没有就沿着__proto__ 找原型对象。
.如果原型对象上还没有,继续沿着__proto__,直到找到Object的原型对象对象。
.如果还没找到就返回undefined
.原型链:沿着__proto__查找的这条链就是原型链
16、再谈instanceof
.A instanceof B
工作原理,从A为起点,在整个原型链上找有没有B原型结点
17、变量提升和函数提升
.js引擎在js代码正式执行之前会做一些预解析的工作。
.找关键字 var function
.找到var以后将变量提前声明,但是不赋值
.找到function以后定义对应得函数,也就是说函数在预解析的时候已经定义完毕。
18、执行上下文
.理解:执行上下文抽象的概念,代表了代码执行的环境,包含:执行环境,变量对象,this,作用域链
.流程:
——js引擎在js代码正式执行之前会创建一个执行环境
——进入该环境以后创建一个变量对象,改对象用于收集:变量、函数、函数的参数、this。(找关键字var function)
——确认this的指向
——创建作用域链
——分函数和全局()
——每调用一次函数创建一次执行上下文。
19、注意:
.全局预解析在定义函数的时候不关心函数是否被使用
.函数局部预解析的时候如果内部函数没有被使用就不会提前定义
作用域
19、什么是作用域
.是一个抽象的概念,用来决定代码执行的范围,变量所属的范围
.作用域是代码定义的时候决定的
.作用域作用:
隔离变量
规定之后的作用域链是什么样 体现:[[scopes]] 上级的作用域链
20、作用域链
.是一个数组结构
.该结构内保存的是一个个的变量对象
scopes
闭包
21、闭包产生的条件
.函数嵌套
.内部函数引用外部函数的局部变量
.使用内部函数
22、闭包是什么
.是函数内部对外部函数的变量对象的一个引用关系
.现在我们有这个一段代码
function fun(){
var num = 123;
function fun1(){
alert(num);
}
return fun1;
}
var fun1 = fun();
fun1();
.先来描述下整个过程就是,在栈结构内存定义变量fun,然后在堆区开辟空间创建fun函数对象。然后fun函数被调用,预解析器预解析,创建执行环境,定义变量对象,变量对象收集变量等,然后压栈,因为函数在执行过程中会用到变量,所以fun函数对象就对这个变量对象一个引用关系,使得这个变量对象不会被当作垃圾回收。然后内部函数被使用,被当作返回值返回了,按理说,此时fun函数已经执行完,fun函数对象和fun变量对象之间得引用关系已经断开,此时fun的变量对象应该被销毁,但是fun内的函数fun1中用到了fun的局部变量num,使得fun1函数对象和fun的变量对象建立引用关系。fun的变量对象得以保持,所以没被销毁,所以在下面调用fun1的时候仍然能得到num的值。
23、
.自己有一个问题,怕忘记了,先记录下来,就是在fun函数调用前,fun1函数被定义,此时fun1[[scopes]]中有了fun的变量对象和全局的变量对象了,那么当fun1运行的时候为什么在自己作用域链里找不来num变量的,是因为 [[scopes]]里对象是变量对象的引用吗? 调试的时候我也发现了,假如num变量没有在fun1中使用,那么fun1的[[scopes]]里就只剩下了全局变量对象。
24、常见的闭包
.将函数作为另一个函数的返回值
.将函数作为实参传递给另一个函数调用
.使用闭包实现私有方法操作独立的私有属性
25、闭包的作用
.延长外部函数变量对象的生命周期
.让函数外部可以操作到函数内部的数据
26、闭包的生命周期
.产生:在嵌套的内部函数定义执行完时就产生,而不是在调用时才产生。
.死亡:在嵌套的内部函数成为垃圾对象时
27、闭包的优缺点
.延长外部函数变量对象的生命周期
占内存
28、注意
.及时清除闭包
.让内部函数成为垃圾对象,即让内部函数没有外部函数变量对象的引用
继承
29、原型继承
.子类的原型 成为父类的实例
.constructor属性要自己指定
.Child.prototype = new Parent();
会导致子类的构造器属性丢失,所以加一行
Child.prototype.constructor = Child;
30、借用构造函数继承(不是真的继承)
.核心思想: 让父类的方法在子类中执行
.注意问题:如果父类的方法在子类中直接调用,会导致window对象身上添加了不必要的属性。
.解决: 使用call 或 apply
31、组合继承
.核心思想:原型继承 + 借用构造函数继承
32、js事件循环(轮询)机制
.js是单线程的 - 》主线程
.同步任务 和 异步任务
同步:阻塞的,同步没有回调
异步:非阻塞的,异步有回调(用来通知当前异步任务执行的结果)
.定时器真的准时吗?不一定
特例:定时器任务的后面有运算量大的代码段。
.事件轮询机制:
。js任务都会在js的主线程执行
。当开启一个异步任务的时候会交给对应得管理模块去管理
。主线程继续执行后续的任务
。管理模块接管的对应的回调,它会在恰当的时机讲对应的回调放入callback queue中
。当主线程上所有的同步任务执行完毕会通过“轮询方式”询问callback queue是否有可执行的回调
。假如没有会反复询问
。假如有可执行的回调将对应的回调钩到主线程执行
.开发注意事项:
不要在定时器任务之后放置运算量大的代码段;
33、
.for in 枚举对象的时候除了能够枚举自身的属性之外还会枚举原型的属性。一般会和hasOwnProperty配合使用。
34、
.Object.create()
35、
.bind 修改this指向后返回函数。不调用
ES6
36、let
.作用:同var一样用来声明变量
.变量提升:
-全局变量提升:会创建一个变量对象(script)用来收集全局作用域下let定义的变量,但是没有赋值。
-局部变量提升:会将var let定义的变量全部放到当前函数的变量对象中。
-区别:let提升的变量在为赋值之前不允许使用。
37、const
.用于定义一个常量
38、箭头函数
简洁
箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的上下文对象就是它的this
箭头函数不能当作构造函数去使用,因为它的this并没有执行新创建的那个对象。
39、自己实现iterator
<script>
let arr = [1,2,3,4,5];
function iteratorUtil(){
let index = 0;
return {
next:()=>
index<this.length?{value:this[index++],done:false}:{value:this[index++],done:true}
}
}
Array.prototype[Symbol.iterator] = iteratorUtil;
for(let item of arr){
console.log("hello");
console.log(item);
}
console.log(arr);
</script>