js 函数 this

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/nayi_224/article/details/88143816

其实关于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

有时间再收集一些。

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

猜你喜欢

转载自blog.csdn.net/nayi_224/article/details/88143816
今日推荐