JavaScript之this解密

来源:互联网 发布:重庆数据恢复发 编辑:程序博客网 时间:2024/05/16 18:31
JS中的this一直是个比较头疼的问题,这里我总结了一下this的四种场景
一 this的四种调用模式:
函数除了声明时定义的形参外,还接受两个附加参数:this和arguments(实参对象)
thius的值取决于调用的模式在js中一共有四种调用模式:方法调用函数调用构造器调用通过call或apply间接调用模式
1.1方法调用
当函数被保存为对象的一个方法是,我们称它为方法,通过。点表达式或者[]表达式调用。
这时this绑定到该对象上。
var myObject = {
value:0,
inctement: function (inc) {
this.value += typeof inc === 'number' ? inc : 1
}
}
myObject.increment(1) .......//1
myObject.increment(2) .......//2
1.2 函数调用
当函数并非一个对象的属性时,this绑定到全局对象(非严格模式下)或者undefined(严格模式下),这时语言设计的错误。
BUT我们有一个容易的解决方案:如果你想要访问这个外部函数的this,需要将this的值保存在一个变量里面,这个变量和内部函数都在同一个作用域里。
myObject.double = function() {
var self = this;
var helper = function () {
that.value = add(that.value,that.value)
}
helper() //这里是以函数的形式调用helper
}
myObject.double()
1.3一个函数,它创建的目的就是希望结合new来调用,那么就可以称它为构造器函数
如果一个函数前面加上new,那么背地里将会创建一个连接到该函数的prototype成员的新对象,同时this会绑定到那个新对象上面。
//创建一个构造器函数
var Quo = function (string) {    this.status = string}//添加公用方法Quo.prototype.getStatus = function () {    return this.status}//创建一个Quo实例var myQuo = new Quo('4543')              .........//4543  
1.4 call和apply都可以显式的置顶调用所需的this值,换言之:任何函数都可以作为任何对象的方法来调用,及时这个函数不是那个对象的方法。
call()方法使用它自有的参数列表作为函数的参数,而apply()则要求一数组的形式传入参数。
比如找出数组中的最大值
var arr = [1,23,4,54,6,23]Math.max.apply(Math,arr) Math.max.call(Math,...arr)     
拿一个通俗易懂的例子:
var a = function{ 我能下蛋}var b = 公鸡 a.call(b)    ......//公鸡可以下蛋啦 这里的this就是指的公鸡了。
讲到call,和apply就要说一下bind()了,EMCAScript5新增的bind方法,主要的作用就是将函数绑定到某个对象,看一下例子,当在函数f()上调用bind()方法并传入一个对象o作为参考,这个方法将返回
一个新的函数,当(以第二种函数调用的方式)调用新的函数时,将会把原始的函数f()作为0的方法来调用。传入新参数的任何实参,都会传入到原始函数中。
function f(y) {    return this.x +y}var 0 = {x:1}var g = f.bind(o)        .......//通过调用g(x)来调用o.f(x)g(2)                           ......//3
这里用apply()方法简单实现模拟bind()
function bind(f,o) {    if (f.bind) return f.bind()    else return function() {        return f.apply(o,arguments)        //return f.call(o,...arguments)}}
bind()方法不仅仅是吧函数绑定到一个对象上,还附带其他应用,除了第一个实参之外,传入bind()的实参也会绑定到this。(函数式变成技术,有时也成为"柯里化")
eg1:
var sum = function() {return x + y}var succ = sum.bind(null,1)succ(2)    ...........//   3    x绑定到1,并传入2作为实参y
eg2:
var sum = function() {return this.x + y + z}var g = sum.bind({x:1},2)g(3)            ........... 6     this.x绑定到1,y绑定到2,z绑定到3
当然有一些特性call和apply是模拟不了的比如bind方法返回的函数是不包含prototype的(普通函数固有的prototype是不能删除的)
原创粉丝点击