JavaScript迷之this总结

xiaoxiao2021-02-28  64

JavaScript的this迷之指向是不是弄晕了你,我是被转的晕头转向,所以来总结一下this的指向问题。

this的指向总体可以分为四种情况:

直接调用作为对象方法调用构造函数调用call()跟apply()方法调用

在说this的指向之前,我们先要知道this是在函数调用的时候确定的,这使得我们可以非常灵活的使用this,所以这才叫迷之this。

直接调用

废话不多说,直接上码

var name = "xiaoming"; function getName() { var name = "xioahong"; console.log(this.name); // xiaoming console.log(this === window); // true } getName();

上面的例子可以说明函数独立调用的使用this指向全局window,但是如果在严格模式会报错。

顺便一提,ES6已经默认使用严格模式。

看了上面的例子,不要以为只有全局作用域独立调用函数,this才指向全局window,其实在任何作用域像 函数名() 这样的独立调用函数的this都指向全局window。

function getName() { function personName() { console.log(this === window); // true } return personName; } getName()();

或许有人看不懂getName()();这个的意思,其实就是在调用getName函数再处理它的返回值,就相当于下面的例子。

function getName() { function personName() { console.log(this === window); // true } personName(); } getName();

而在接触this后,你是否想改变this的指向,可是this的指向是不可以改变的,我们先来看下this指向不可改变。

var obj = { name: "xiaoming" } function getName() { this = obj; console.log(this.name); } getName(); // 运行报错 2.作为对象的方法的调用

先上两个例子

var name = "xiaohong"; var obj = { name: "xiaoming", getName: function() { console.log(this.name); // xiaoming console.log(this === obj); // true } } obj.getName(); (obj.getName)(); // 结果与上面调用方式相同 // 这只是在引用一个函数,所以this指向保持不变 var name = "xiaohong"; var obj = { name: "xiaoming", getName: function() { console.log(this.name); // xiaohong console.log(this === obj); // false } } var fn = obj.getName; fn();

乍一看上面两个例子没有什么区别,但是区别很大: 例1调用obj对象里面的getName()方法,所以this指向obj; 例2将obj.getName的引用赋值给变量fn,之后又独立调用,说以this指向了全局Window

在此总结: 如果调用函数被一个对象所拥有,则该函数内部的this指向该对象。 如果函数单独调用,则this指向全局window,在严格模式下报错。 (调用匿名函数在我的理解中也相当于函数独立调用)

来个简单的自执行函数来证明一下

(function() { console.log(this === window); // true })();

我们来看下下面这个例子

var name = "global"; var obj = { name: "local", getName: function() { return function() { // 该匿名函数为闭包 return this.name; // 返回的是? }; } }; console.log(obj.getName()());

这个答案当然是 "global" 。因为我们知道每个函数在调用的时候会获取两个对象:this和arguments。而内部函数在搜索这个两个对象时只会搜索到其活动对象为止。而匿名函数的执行环境具有全局性,所以这个this就指向了全局window。

但我们要访问匿名函数的外部函数变量的话要怎么做?看这里。

var name = "global"; var obj = { name: "local", getName: function() { var that = this; return function() { return that.name; // local }; } }; console.log(obj.getName());

我们不可以改变this的值,但我们可以把this用变量存储起来,这样this的指向就不会变了。

3.构造函数调用 function Person(name, age) { this.name = name; // 此处this的指向是? this.age = age; } var person = new Person("xiaoming", 22); console.log("name:" + person.name + ",age:" + person.age);

参考JavaScript高级程序设计,我们可以知道new操作符做了四件事:

创建一个新对象将构造函数的作用域赋给了新对象(因此this指向了该对象)执行构造函数中的代码(为这个新对象添加属性)返回新对象

所以上面的打印结果是: name:xiaoming,age:22

4.使用call()跟apply()方法绑定this

先来看下定义

call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。

apply方法: 语法:apply([thisObj[,argArray]]) 定义:应用某一对象的一个方法,用另一个对象替换当前对象。 说明: 如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。 如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数

我们来看下怎么绑定this

var obj = { name: "xiaoming" } function getName() { console.log(this.name); // xiaoming } getName.call(obj);

其实在我的理解中call跟apply是没有什么区别,只是传递参数的形式不一样。 call():一个一个的传递参数; apply():以数组的形式传递。

var obj = { num1: 1 } function count(num2, num3) { console.log(this.num1 + num2 + num3); } count.call(obj, 1, 1); // 3 count.apply(obj, [1, 1]); // 3

使用call()跟apply()可以借用其他对象的方法。 例如:借用Math()对象的最大值方法找出数组中的最大值

var arr = [2,34,54,23,233,44], maxNum = Math.max.apply(Math, arr); console.log(maxNum); // 233 作者: 关于郑州想的都是你  链接:http://www.imooc.com/article/17159 来源:慕课网
转载请注明原文地址: https://www.6miu.com/read-37157.html

最新回复(0)