绝大多数情况下,函数的调用方式决定了this的值。
全局环境(在任何函数体外部)
console.log(this === window); // true但是,module除外:module中全局环境里的this为undefined
函数中
取决于函数被谁调用,被如何调用……
//'use strict';
function hello() {
console.log(this === window);
}
hello();
非严格(window) v.s 严格(undefined)
var o = {
hello: function () {
console.log(this === o);
}
}
o.hello();
注意:this只受“运行时”影响,不受定义时影响(和“文本作用域”区别)。这样的写法也是一样的:
var o = {};
o.hello = function () {
console.log(this === o);
};
o.hello();
<button onclick="alert(this.tagName.toLowerCase())">
Show this
</button>
但这样是不行的:
<button onclick="show()">
Show this
</button>
<script>
function show() {
//alert(this === window);
alert(this.tagName.toLowerCase());
}
</script>
需要改成:
<button onclick="show(this)">
Show this
</button>
<script>
function show(that) {
alert(that.tagName.toLowerCase());
}
</script>
同一个function,因为不同的调(使)用方式,就会导致不同的结果,这是非常“荒谬”的一件事情。
复杂多变的this会带来很多不便,比如:
function Student() {
this.age = 0;
setInterval(function () {
this.age++;
}, 1000);
}
var wf = new Student();
@想一想@:为什么age没有增加?
之前的hack办法:
function Student() {
var that = this;
this.age = 0;
setInterval(function () {
that.age++;
}, 1000);
}
箭头函数(=>)可以完美的解决这个问题。
箭头函数:=>
使用匿名函数的地方,就可以使用箭头函数(C#中Lambda表达式)function (x) {
return x * x;
}
//等同于:
x => x * x;
传入参数:
(x, y) => {return x * y;}
x => {return x * x;}
() => { console.log('源栈欢迎您'); }
方法体:
x => {return x * x;};
等于:
x => x * x;
注意:因为箭头函数中不会生成this,即:箭头函数中的this只会被当做一个普通变量,所以this只会按作用域链向上继续寻找。
总体而言,箭头函数适用于方法(面向对象)。
Apply和Call
使用Function对象(function名称)的apply()和call(),可以直接调用方法。第一个参数即方法体内的this,其他参数就是Function对象的参数。
区别:
function hello(sname) {
console.log(sname + this.age);
}
hello.call({ age: 37 }, '飞哥');
Bind
使用Function对象(function名称)的bind()方法,创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
let greet = hello.bind({ age: 37 }, '飞哥');
注意:如果第一参数不是object,就会被默认使用ToObject()转换成object,比如:7 => new Object(7)
7.toString() new Object(7).toString()
作业:
var sname = "飞哥";
var a = {
sname: '老程',
fn: function () {
console.log(this.sname);
}
}
请用不同的方式调用fn()函数,能分别打印出‘飞哥’和‘老程’
多快好省!前端后端,线上线下,名师精讲
更多了解 加: