原型与原型链
原型
- 函数都带有一个prototype 属性,这是属性是指向构造函数的原型对象,这个对象包含所有实例共享的属性和方法。
- 原型对象都有一个constructor 属性,这个属性指向所关联的构造函数。
- 每个对象都有一个__proto__ 属性[非标准的方法],这个属性指向构造函数的原型 prototype
原型链
- 当访问实例对象的某个属性时,会先在这个对象本身的属性上查找,如果没有找到,则会 通过 __ proto __ 属性去原型上查找,如果还没有 找到则会在构造函数的原型的__ proto__中查 找, 这样一层层向上查找就会形成一个作用域链,称为原型链
执行上下文与执行上下文栈
变量提升与函数提升
- 变量提升: 在变量定义语句之前, 就可以访问到这个变量(undefined)
- 函数提升: 在函数定义语句之前, 就执行该函数
- 先有变量提升, 再有函数提升
理解
- 执行上下文: 由js引擎自动创建的对象, 包含对应作用域中的所有变量属性
- 执行上下文栈: 用来管理产生的多个执行上下文
分类
- 全局: window
- 函数: 对程序员来说是透明的
生命周期
- 全局 : 准备执行全局代码前产生, 当页面刷新/关闭页面时死亡
- 函数 : 调用函数时产生, 函数执行完时死亡
包含哪些属性:
- 全局 :
- 用var定义的全局变量 ==>undefined
- 使用function声明的函数 ===>function
- this ===>window
- 函数
- 用var定义的局部变量 ==>undefined
- 使用function声明的函数 ===>function
- this ===> 调用函数的对象, 如果没有指定就是window
- 形参变量 ===>对应实参值
- arguments ===>实参列表的伪数组
执行上下文创建和初始化的过程
- 全局:
- 在全局代码执行前最先创建一个全局执行上下文(window)
- 收集一些全局变量, 并初始化
- 将这些变量设置为window的属性
- 函数:
- 在调用函数时, 在执行函数体之前先创建一个函数执行上下文
- 收集一些局部变量, 并初始化
- 将这些变量设置为执行上下文的属性
作用域与作用域链
理解:
- 作用域: 一块代码区域, 在编码时就确定了, 不会再变化
- 作用域链: 多个嵌套的作用域形成的由内向外的结构, 用于查找变量
分类:
- 全局
- 函数
- js没有块作用域(在ES6之前)
作用
- 作用域: 隔离变量, 可以在不同作用域定义同名的变量不冲突
- 作用域链: 查找变量
区别作用域与执行上下文
- 作用域: 静态的, 编码时就确定了(不是在运行时), 一旦确定就不会变化了
- 执行上下文: 动态的, 执行代码时动态创建, 当执行结束消失
- 联系: 执行上下文环境是在对应的作用域中的
闭包
-
理解:
- 当嵌套的内部函数引用了外部函数的变量时就产生了闭包
- 通过chrome工具得知: 闭包本质是内部函数中的一个对象, 这个对象中包含引用的变量属性
-
作用:
- 延长局部变量的生命周期
- 让函数外部能操作内部的局部变量
-
写一个闭包程序
function fn1() { var a = 2; function fn2() { a++; console.log(a); } return fn2; } var f = fn1(); f(); f(); -
闭包应用:
- 模块化: 封装一些数据以及操作数据的函数, 向外暴露一些行为
- 循环遍历加监听
- JS框架(jQuery)大量使用了闭包
-
缺点:
- 变量占用内存的时间可能会过长
- 可能导致内存泄露
- 解决:
- 及时释放 : f = null; //让内部函数对象成为垃圾对象
内存溢出与内存泄露
- 内存溢出
- 一种程序运行出现的错误
- 当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误
- 内存泄露
- 占用的内存没有及时释放
- 内存泄露积累多了就容易导致内存溢出
- 常见的内存泄露:
- 意外的全局变量
- 没有及时清理的计时器或回调函数
- 闭包
call、apply、bind三者的异同
- 共同点 : 都可以改变this指向;
- 不同点:
- call 和 apply 会调用函数, 并且改变函数内部this指向.
- call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递
- bind 不会调用函数, 可以改变函数内部this指向.
- 应用场景
- call 经常做继承.
- apply经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值
- bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向
cookie和session 的区别
- 1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
- 2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
- 考虑到安全应当使用session。
- 3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
- 考虑到减轻服务器性能方面,应当使用COOKIE。
- 4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
- 5、所以个人建议:
- 将登陆信息等重要信息存放为SESSION
- 其他信息如果需要保留,可以放在COOKIE中
ES6中的class类
es6中的class可以把它看成是es5中构造函数的语法糖,它简化了构造函数的写法, 类的共有属性放到 constructor 里面
-
通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
-
类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
-
constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
-
多个函数方法之间不需要添加逗号分隔
-
生成实例 new 不能省略
-
语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
-
继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
-
继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
-
如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用 父类的构造函数,super 必须在子类this之前调用
-
-
时刻注意this的指向问题,类里面的共有的属性和方法一定要加this使用.
-
constructor中的this指向的是new出来的实例对象
-
自定义的方法,一般也指向的new出来的实例对象
-
绑定事件之后this指向的就是触发事件的事件源
-
在 ES6 中类没有变量提升,所以必须先定义类,才能通过类实例化对象
-
数据类型的判断有哪些方法?他们的优缺点及区别是什么?
然后判断数据类型的方法一般可以通过:typeof、instanceof、constructor、toString四种常用方法
| 不同类型的优缺点 | typeof | instanceof | constructor | Object.prototype.toString.call |
|---|---|---|---|---|
| 优点 | 使用简单 | 能检测出引用类型 | 基本能检测所有的类型(除了null和undefined) | 检测出所有的类型 |
| 缺点 | 只能检测出基本类型(出null) | 不能检测出基本类型,且不能跨iframe | constructor易被修改,也不能跨iframe | IE6下,undefined和null均为Object |