this
与变量索值不同,this的值在执行上下文中
通常情况下,如果没有在方法后面添加 (),例如 onClick={this.handleClick},你应该为这个方法绑定 this。
函数可以关联至一个对象,这时称之为方法。对象被隐式传递给其所调用的方法,方法可以访问和操作对象里的数据,通过 this 关键字引用对象。
当函数作为对象的方法被调用时,this 指向该对象
普通函数调用,即普通函数方式,此时的 this 总是指向全局对象
构造器里的 this 就指向返回的对象
构造器调用的返回值
返回:对象本身:构造器无显性返回值,或者是返回一个非对象类型的数据
var MyClass = function(){
this.name = 'sven';
};
var obj = new MyClass();
alert ( obj.name ); // 输出:sven指向new的对象
var MyClass = function(){
this.name = 'sven'
return 'anne'; // 返回 string 类型
};
var obj = new MyClass();
alert ( obj.name ); // 输出:sven
构造器显式地返回了一个 object 类型的对象
var MyClass = function(){
this.name = 'sven';
return { // 显式地返回一个对象//花括号封装对象
name: 'anne'
}
};
var obj = new MyClass();
alert ( obj.name ); // 输出:anne
返回值是一个函数
func执行结束后返回一个part函数,再次()调用返回值,执行part函数。part函数返回自己,所以可以一直调用下去。
var func = function(x){
var way = "func";
var part = function(x){
console.log("这里是函数的成员变量part");
way = way +"+part";//没用var,全局变量诶
return part;
}//报错?还没有建立好
part.toString = function(){
return way;
}//alert默认打印出函数体,修改为way的值
console.log("这里是func");
return part;
}
alert(func(1)(2)(3)());//
运行结果
其次想到了之前的报错,对比这里并没有访问undefined的对象的属性,所以不报错
前提
bind 是 ES5 中新增的一个方法,可以改变函数内部的this指向,是ES6中箭头函数绑定this的基础。
大部分高级浏览器都实现了内置的 Function.prototype.bind,call、apply语法是bind的基础。
bind与call、apply区别于立即执行还是等待执行。
bind语法:
func.bind(thisArg[, arg1[, arg2[, …]]])
thisArg 当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new 操作符调用绑定函数时,该参数无效。
arg1, arg2, … 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
注意,除了把函数绑定到对象上,bind方法还会将其他参数做绑定
let sum=(x,y)=>x+y;
let suc=sum.bind(null,1);//x=1
suc(2);//3
没有原生的 Function.prototype.bind 实现,我们也可自己写代码如下:
加入了一些输出来观察整个过程
var name="xxx";//全局的name
Function.prototype.bind = function( context ){
var self = this; // 保存原函数
console.log("2bind执行中");
return function(){ // 返回一个新的函数
//新函数的执行体为空,只有返回值
console.log("4执行bind返回的func");
return self.apply( context, arguments ); // 执行新的函数的时候,会把之前传入的 context
// 当作新函数体内的 this
}
};
var obj = {
name: 'obj'
};
console.log("1绑定前的全局name属性是"+ this.name );
var func = function(){
console.log("5这里在执行 被绑定的函数");
console.log( "6"+this.name ); // 输出:obj
}.bind( obj);
console.log("3bind完毕,下面开始调用绑定的返回值");
func();
bind() 函数会创建一个新函数(称为绑定函数)作为返回值,不执行被调函数。新函数与被调函数(绑定函数的目标函数)具有相同的函数体,实质上新函数就是返回一个对被调函数实施apply。当新函数被调用的时候实质上执行了两个函数体:新函数(apply)+被调函数。
常见应用实例
调用函数和编写函数的时候格外注意this
<html>
<body>
<div id="div1">我是一个 div</div>
</body>
<script>
var getId = document.getElementById;
getId( 'div1' );
</script>
</html>
抛出了一个异常。这是因为许多引擎的 document.getElementById 方法的内部实现中需要用到 this。这个 this 本来被期望指向document,当 getElementById 方法作为 document 对象的属性被调用时,方法内部的 this 确实是指向 document 的。但当用 getId 来引用 document.getElementById 之后,再调用 getId,此时就成了普通函数调用,函数内部的 this 指向了 window,而不是原来的 document。
可以尝试利用 apply 把 document 当作 this 传入 getId 函数,帮助“修正”this:
document.getElementById = (function( func ){
return function(){
return func.apply( document, arguments );
}
})( document.getElementById );
var getId = document.getElementById;
var div = getId( 'div1' );
alert (div.id); // 输出: div1
div 节点的 onclick 事件
假如该事件函数中有一个内部函数 func,在事件内部调用 func 函数时,func 函数体内的 this就指向了 window,而不是我们预期的 div,见如下代码:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 输出:div1
var func = function(){
alert ( this.id ); // 输出:undefined
}
func(); //func.call( this ); 修正 func 函数内的 this,使其依然指向 div:
};