欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

js 函数 this

程序员文章站 2022-03-04 22:16:16
...

其实关于js中的this到底是个什么东西,我看了N多资料都没搞清楚。反正不是全局作用域就是某个对象,那就用笨方法,把所有用到this的情况都写一遍,看看能不能从中找到什么规律吧。

本文使用非严格模式测试、浏览器环境(360、谷歌)



各种我能想到的例子

		function aaa(){
			alert(this === window);
		}
		
		aaa();  //true

this指向全局作用域

由于aaa()可以算是window.aaa()的简写,那会不会是与这个window有什么直接关系呢?于是写了下面的例子

		function b(){
			function bb(){
				alert(this === window);	//true
			}
			bb();
		}
		
		window.b();

应该也不是这种关系,因为在b函数内无法使用window.b.bb();这样的语句。

那么看起来就是,用function xxx(){}这样的方式定义的函数的方法体内,this指的就是window(全局变量)。真的是这样么?

		function f1(){
			alert(this === a); //true
		}
		
		function f2(){
			function ff2(){
				alert(this === window); //true
			}
			ff2();
		}
		
		var a = {
			aaa: f1,
			bbb: f2
		};
		
		a.aaa();
		a.bbb();

坑爹的事情发生了,它们都返回true。也就是说,this指代的对象,一个是a,一个是window

这时再回过头来想一下看过无数遍的那句话:***this的值取决于调用方式***

  • f1中this的指向问题看来是解决了。a是window中的一个对象,所以通过a调用时,this被绑定成了a

  • 对于ff2中的this,就有些奇怪了。无论用什么样的方式调用,都指向的window。于是可以这样认为:对于这种直接定义的函数(function xxx(){}),当采用xxx()的形式调用时,内部的this就是指向window的。(我对这样的结论非常不满意,这实在是有些不严谨,但是又找不到反例,就先这么认为吧)

看来this确实是取决于调用方式的。再写几个例子来加深印象吧。

//匿名函数返回对象的方式调用
		function f1(){
			console.log(this);
		}
		
		var aaa = function(){
			return {
				f1: f1
			}
		}();
		
		aaa.f1();	//指向aaa
		f1();	//指向window

不需要解释。

//多重嵌套下的调用
		function f1(){
			console.log(this === bbb);	//true
		}
		
		var bbb = {
			b1: f1
		};
		
		var aaa = {
			a1: bbb
		}
		
		aaa.a1.b1();

f1是由a1直接调用的,a1就是bbb。可以得出,this指向的是最近的、直接调用的对象。这很符合直观印象。

//在上述基础上改一下,将值赋予一个全局变量后再调用
		function f1(){
			console.log(this === window); //true
		}
		
		var bbb = {
			b1: f1
		};
		
		var aaa = {
			a1: bbb
		}
		
		var ccc = aaa.a1.b1;
		
		ccc();

这是作为全局变量(ccc)来调用的,所以this指的也是window。

//通过new创建的函数
		var a = function(){
			var that = this;
			this.f1 = function(obj){
				console.log(this === obj);	//true
				console.log(that === obj);	//true
			}
		};
		
		var b = new a();
		
		b.f1(b);

可以的出this指代的是实例化对象。

。。。。。。

同样的一段代码通过不同的方式调用竟然可以出现不同的结果,这真是一大败笔。
既然它这么坑,那官方肯定也是提供了一套解决方案的,那就是显式的指定this。

call apply

语法
call(thisObj, parameter1, parameter2 …)
apply(thisObj, [parameter1, parameter2 …])
这两个方法都是有函数本身调用,不同的是call需要将参数一个一个传入,apply则是将参数列表作为一个数组传入。

用call来改写一下上面的语句

		var a = function(){
			var that = this;
			this.f1 = function(obj){
				console.log(this === window);	//true
				console.log(that === obj);	//true
			}
		};
		
		var b = new a();
		
		b.f1.call(window, b);

可以看得出,call将f1的this显式的指定为了window。不过,a中的this依然指的是a的实例化对象,这也正是我们想要的结果。

收集来的一些练习题

基本都涉及一些this之外的知识点

  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()());
  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()());
  //https://www.zhihu.com/question/21172721/answer/17413362
var age = 3;
var cat1 = new function() {
    this.name = 'Tom';
    this.age = 2;
    this.weight = function(age) {
        var age = age * 2;
        var _age = this.age * 2;
        return 'weight by age:' + age + '; weight by this.age:' + _age;
    }(this.age);
    this.eye = new function() {
        this.size = '1.5cm';
        this.color = 'red';
    };
    this.catching = function(mouse) {
        return this.name + ' is catching ' + mouse;
    };
};
alert(cat1.weight);
alert(cat1.eye.color);
alert(cat1.catching('Jerry'));
//https://www.cnblogs.com/pizitai/p/6427433.html
var personA={
    name:"xl",
    showName:function(){
        console.log(this.name);
    }
}
var personB={
    name:"XL",
    sayName:personA.showName
}
personB.sayName();
		var myObject = {

			foo: "fff",
			func: function() {

				var self = this;
				console.log("outer func : this.foo = " + this.foo);
				console.log("outer func : self.foo = " + self.foo);

				(function() {
					console.log("inner func : this.foo = " + this.foo);
					console.log("inner func : self.foo = " + self.foo);
				}());
			}
		}
		myObject.func();
//看来内部的匿名自执行函数的this也是指代的全局对象
var length = 10;
function fn() {
    console.log(this.length);
}
 
var obj = {
  length: 5,
  method: function(fn) {
    fn();
    arguments[0]();
	console.log(arguments);
  }
};
 
obj.method(fn, 1);
//每当你觉得自己会了的时候,总会有这样的一道题来击碎你的幻想......
//https://blog.csdn.net/sinat_36521655/article/details/80253311

有时间再收集一些。

网上收集的例子很多都不严谨,如果本文有什么错误,欢迎指正。

相关标签: js基础