this
this的值由函数的调用方式决定(注意直接调用和引用后调用的区别),并且不能在执行期间被赋值。
-
直接调用时:
- 在非严格模式下,默认指向全局对象(window/global)
- 在严格模式下,保持其进入执行上下文时的值。
-
bind/call/apply:
产生和目标函数相同函数体和作用域的新函数,同时永久改变其this的指向。- bind 返回新函数,不调用
- call的参数2及以后的参数是新方法调用的一个个参数
- apply的参数2是新方法调用时的参数数组
箭头函数内:
指向其被创建时的上下文-
作为对象的方法:
指向调用该函数的对象(最靠近的引用成员)定义匿名函数后附属到某对象,再在对象上调用之,仍产生相同行为
getter/setter内:
指向正在设置或获取属性的对象构造函数内:
指向正在构造的新对象(构造器默认返回该对象,也可以手动返回其它对象)作为事件处理函数时:
指向触发事件的元素(e.target)
原型和继承
- 函数的
prototype
是一个对象(默认只有一个指向构造函数自身的constructor
属性),当这个函数被用作构造函数来创建实例时,其prototype
将被作为__proto__
赋值给所有对象实例 - 定义
prototype
的过程实际上就是将该构造函数之实例的__proto__
指向某一结构体的过程,该属性等于其构造函数的原型属性,默认指向Object
- 除了
Object.prototype
, 所有对象的__proto__
引用其构造函数的prototype
。 - 遍历对象属性时一般应使用
hasOwnProperty()
过滤掉继承自原型链的属性。 - 继承另一函数的实例时(如将构造函数A的原型改为构造函数B的实例),会将A的
constructor
也改为构造函数B,此时必须将A的constructor
改回来。
作用域
- 预编译时声明所有变量和函数,为表达式创建的变量和函数赋
undefined
值,为this
和定义式创建的函数赋给定值。此为第一次运行上下文的创建:- 函数的每次调用都会产生新的运行上下文(包含由实参、形参、内部函数和变量、
this
共同组成的活动对象,此对象被推入作用域链的前端)。每个运行上下文在该函数调用结束且未产生闭包时被销毁。
- 函数的每次调用都会产生新的运行上下文(包含由实参、形参、内部函数和变量、
- 作用域是函数被创建的作用域中对象的集合,决定了其可以访问哪些数据。函数运行在其被定义的作用域里,而不是被执行的作用域里。
- 标识符的值从作用域链的前端向末端查找,位于作用域链越深处的标识符,其读写速度就会越慢。故将被引用一次以上的跨作用域对象保存在局部变量中后再使用可提升性能。
- 不使用
var
关键字可定义全局变量的过程,实际上就是对从作用域链前端至末端(window
全局对象)都未找到的、故其值为undefined
的变量赋值的过程。 -
with
和catch
语句会改变运行时的作用域链:前者将新的目标作用域推入了作用域链前端,原局部变量处于第二个作用域对象中,损失性能,不建议使用;后者将异常对象推入作用域链前端,原局部变量处于第二个作用域对象中,在catch
语句结束后恢复原状态。 - JS预编译时以每个
<script>
标签作为编译单元,此标签内以任何方式定义的属性和函数均无法在此标签之前的单元内直接使用。故功能性的脚本标签必须置于其它脚本之前。