首先要搞清:
this是执行上下文(execution context)的属性 而不是变量对象(variable object)的属性。进入当前执行上下文,this值即以确定。
this不会参与到标识符解析过程(不会去作用域链中查找),它的值是直接从执行上下文中获取的。
this的值与函数调用方式密切相关:
方法调用模式
当函数被当作对象的方法(method)调用时,this会绑定到该对象。
var obj={
name:'test',
fun:function(){
console.log(this.name) //test
}
}
obj.fun()
obj['fun']()
函数调用模式
当一个函数并非某个对象的属性 其调用时,this 指向全局对象(严格模式 下this值为undefined),浏览器中就是window了。
function fun1 () {
console.log(this)//Window
function fun2() {
console.log(this)//Window
}
fun2()
}
fun1()
构造器调用模式
构造函数用new调用,调用时背地里会创建一个连接到该函数prototypes属性的新对象,同时this也会绑定到该对象上。若构造函数返回值不是 一个对象(primitive value,或未明确指定返回值),则返回this。
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);
apply call bind 模式
call()和apply()
call apply 可以改变函数执行上下文中 this 的指向。当某个方法并不存在于某个对象 可以借助call或apply在该对象上调用该方法。
因为很像所以在很多情况下可以用两者均可
比如传统的继承写法中调用父构造函数:
call()和apply()的区别在于:
- 借用call调用某方法时,该方法的参数会通过call的第一个之后的参数 以若干个参数的列表的形式传入。
- 借用apply调用某方法时,该方法的参数会通过call的第二个参数 以一个包含多个参数的数组或类数组对象的形式传入。
因为这点不同 以下情况用apply()就非常合适, 而用call()就不合适了。
var numbers = [1, 2, 3, 4 ];
var max = Math.max.apply(Math, numbers); //4
var max = Math.max.call(Math,1, 2, 3, 4); //4 这样就画蛇添足了。
bind()
bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
bind 和与其他两者有个重要区别: bind 是在函数定义阶段指定函数执行上下文的this指向,绑定之后不会立即去调用。
关于bind call 和apply 要再写一篇总结详谈。
ES6 箭头函数中的this
箭头函数里面根本没有自己的this而是引用外层的this。
正因如此 在react中才可以这么用
//constructor中使用“箭头”(=>)定义各种handle方法。函数内部的this其实就是组件实例。
constructor(props) {
super(props);
this.state = {
}
this.cancelDelete = () => {
const hid = this.props.host.hid;
this.props.actions.cancelDelete(hid)
}
this.confirmDelete = () => {
const hid = this.props.host.hid;
this.props.actions.confirmDelete(hid)
}
}
//在render 中绑定事件时,就省去了手动绑定this的麻烦。
render(){
return(
<button onClick={this.confirmEdit}>保存 </button>
<buttononClick={this.cancelEdit}>取消</button>
)
}