绝大多数情况下,函数的调用方式决定了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()函数,能分别打印出‘飞哥’和‘老程’
多快好省!前端后端,线上线下,名师精讲
更多了解 加: