15.关于THIS基础情况练习题

115 阅读2分钟

THIS知识点

  1. 函数的执行主体,和执行上下文不是一个概念
  2. this是谁和函数在哪执行,以及在哪定义没有必然的联系

按照以下规律来确定执行主体是谁:

  1. 给当前元素的某个事件行为绑定方法,事件触发,执行对应的方法,方法中的this是当前元素本身(排除:IE6~8基于attachEvent实现的DOM2事件绑定,绑定方法中的this不是操作的元素,二是window)
document.body.onclick = function() {
	// this : body
}
  1. 函数执行,首先看函数名之前是否有“点”,有“点”,“点”前面是谁this就是谁,没有“点”this就是window(在JS的严格模式下,没有“点”,方法中的this是undefined)
"use strict" //全局上下文开启严格模式
(function() {
	"use strict" // 当前上下文开启严格模式
)()
2.1  自执行函数中的this一般都是window/undefined<br>
2.2 回调函数中的this一般也是window/undefined<br>

3. 构造函数中的this是当前类的实例

  1. 箭头函数没有自己的this,用到的this都是上下文中的this

  2. 基于call/apply/bind可以强制改变this的指向

练习题

var num = 10
var obj = {
  num: 20
}
obj.fn = (function(num) {
  this.num = num * 3
  num++
  return function(n) {
    this.num += n
    num++
    console.log(num)
  }
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num)

    let obj = {
      fn: (function() {
        return function() {
          console.log(this)
        }
      })()
    }
    obj.fn()
    let fn = obj.fn
    fn()
/**
     * obj.fn = 自执行函数的返回结果
     * fn = 0x000000 (作用域:EC(G),代码字符串“console.log(this)”)
    */
    let obj = {
      fn: (function() {
        return function() {
          console.log(this)
        }
      })()
    }
    obj.fn() // obj.fn() => obj.0x000000() => 输出this:obj
    let fn = obj.fn // fn = 0x00000
    fn() // 输出thiswindown
var fullName = 'language'
var obj = {
  fullName: 'javascript',
  prop: {
    getFullName: function() {
      return this.fullName
    }
  }
}
console.log(obj.prop.getFullName())
var test = obj.prop.getFullName
console.log(test())
var fullName = 'language' // 也会给window一份,window.fullName = 'language'
var obj = {
  fullName: 'javascript',
  prop: {
    getFullName: function() {
      return this.fullName
    }
  }
} // 堆内存0x000000
console.log(obj.prop.getFullName()) //undefined
// this => obj.prop
// this.fullName = obj.prop.fullName => undefined
var test = obj.prop.getFullName
console.log(test()) // 'language'
// this => window
// window.fullName = 'language'
var name = 'window'
var Tom = {
  name: 'Tom',
  show: function() {
    console.log(this.name)
  },
  wait: function() {
    var fun = this.show
    fun()
  }
}
Tom.wait()
var name = 'window'
var Tom = {
  name: 'Tom',
  show: function() {
    console.log(this.name) // fun执行,this => window    window.name = 'window'
  },
  wait: function() {
    var fun = this.show // this => Tom    fun = Tom.show
    fun()
  }
}
Tom.wait()
window.val = 1
var json = {
  val: 10,
  dbl: function() {
    this.val *= 2
  }
}
json.dbl()
var dbl = json.dbl
dbl()
json.dbl.call(window)
alert(window.val + json.val)
window.val = 1 // 第二次执行后变成2
var json = {
  val: 10, // 20
  dbl: function() {
    /**
     * 第一次执行:this => json
     *      json.val *= 2 => 20
     * 第二次执行: this => window
     *      window.val *= 2 => 2
     * 第三次执行:通过call rangthis指向 window
     *      window.val *= 2 => 4
    */
    this.val *= 2
  }
}
json.dbl()
var dbl = json.dbl
dbl() // 
json.dbl.call(window)
alert(window.val + json.val) // 4+20 => 24   alert弹出的都是字符串,缩影应该是'24'
 (function () {
    var val = 1; 
    var json = {
        val: 10,
        dbl: function () {
            val *= 2; 
        }
    };
    json.dbl();
    alert(json.val + val);
})();
 (function () {
    var val = 1; // 第一次执行后 val = 2
    var json = {
        val: 10,
        dbl: function () {
          // dbl 作用域:EC(G)
          // val不是私有的,作用域链想上找 是自执行函数执行创建出来的上下文中的变量
            val *= 2;  // 全局val = 2
        }
    };
    json.dbl();
    alert(json.val + val); // 10 + 2 = 12 => '12'
})();