为什么要使用this
记得小学上英语课的时候,学着介绍自己的名字,每个人都是造一个同样的句型。
普通函数
写法
function myName(name){ |
使用this
写法
function myName(){ |
介绍自己的名字当然比较简单,那么我们来增加点难度。
普通函数
写法
function myName(name){ |
使用this
写法
function myName(){ |
如果不使用this
,那么就需要给myName()
函数显式的传入一个参数name
来代替不同的上下文对象,单单一个参数还可以接受,可随着你的使用模式越来越复杂,显式传递上下文对象会让代码变得越来越混乱。所以,this
提供了一种更优雅的方式来隐式“传递”一个对象的引用,可以将API设计的更加简洁
易于复用
。
this到底是什么?
this
是运行时进行绑定的,是基于函数的执行环境动态绑定
的,而非函数被声明时的环境。
当一个函数被调用时,会创建一个活动记录(也称为上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数 等信息。this
就是这个记录的一个函数,会在函数执行的过程中用到。
this的指向
- 默认绑定(作为普通函数调用,指向
全局对象
) - 隐式绑定(作为对象的方法调用,指向
该调用对象
) - 显式绑定(使用call和apply方法,指向
第一个参数对象
) - new绑定(作为构造函数调用,指向
新创建的对象
)
默认绑定
当函数不作为对象的属性被调用时,也就是我们常说的普通函数方式,此时的this
总是指向全局对象
。
window.name = 'globalName'; |
严格模式
window.name = 'globalName'; |
如果使用严格模式
,则不能将全局对象用于默认绑定。
隐式绑定
当函数作为对象的方法被调用时,this
指向该对象
。
function foo(){ |
对象属性引用链中只有上一层
或者说是最后一层
在调用位置中起作用。
function foo(){ |
显式绑定
Function
的原型定义了两个方法,它们是Function.prototype.call
和Function.prototype.apply
。它们的第一个参数,允许直接指定this
的绑定对象。
function foo(){ |
call和apply的区别
apply
接收两个参数,第一个参数指定了函数体内this
对象的指向,第二个参数为一个带下标的集合,可以是数组
或类数组
,可以将这个集合中的元素作为参数传递。
var func = function(a,b,c){ |
call
传入的参数数量不固定,但是跟apply
相同的是,第一个参数也是代表了函数体内this
对象的指向,之后的参数每个依次传入函数。
var func = function(a,b,c){ |
bind的用法
bind
是把它的上下文绑定到bind()
括号中的参数上,它不会执行
,而只是返回一个改变了上下文的函数副本,而call和apply是直接执行
函数。
var button = document.getElementById("button"), |
new绑定
当用new
调用函数时,会执行以下操作:
- 创建一个全新的对象。
- 新的对象会被执行[Prototype]链接。
- 新对象会绑定到函数调用的
this
。 - 如果函数没有返回其他对象,那么
new
中的函数调用会自动返回这个新对象。
var myClass = function(){ |
判断this && 优先级
优先级
new绑定 > 显示绑定 > 隐式绑定 > 默认绑定
按以下顺序判断:
1、函数是否在 new
中调用(new绑定)?如果是的话this
绑定的是新创建的对象
。
var bar = new foo(); // bar |
2、函数是否通过call
、apply
(显示绑定)或bind
硬绑定?如果是的话this
绑定的是指定的对象
。
var bar = foo.call(obj2); // obj2 |
3、函数是否在某个上下文对象调用(隐式绑定)?如果是的话this
绑定的是那个上下文对象
。
var bar = obj1.foo(); // obj1 |
4、如果都不是的话,使用默认绑定。如果在严格模式
下,就绑定到undefined
,否则绑定到全局对象
。
var bar = foo(); |
参考
你不知道的JavaScript(上卷)
javascript设计模式与开发实践
仅供个人学习记录~