【 总结 】this关键字

本文深入探讨了JavaScript中this的绑定规则,包括默认绑定、隐式绑定、显式绑定、构造函数绑定和严格模式下的行为。通过实例分析了函数调用的各种情况,如独立调用、作为对象方法调用、闭包以及方法别名和参数传递时this的指向变化。同时,文章还介绍了如何通过call、apply、bind方法强制改变this的绑定,并提供了相关练习题加深理解。

// 函数直接调用
function get(content){
	console.log(content)
}
get('Nice')
// 等同于
get.call(window,.Nice)

// 作为对象的方法调用
var person = {
	name:"zwj",
	say:function(){
		console.log(this.name)
	},
	Hello:function(fn){
		fn() // 函数直接使用 fn.call(window)
	}
}
person.say()
// 等同于
person.call(person)

一、默认绑定

  • 全局环境中,this默认绑定到window
  • 函数独立调用时,this默认绑定到window
  • 被嵌套的函数独立调用时,this默认绑定到window

函数独立调用

		// 默认绑定(全局范围)
		function fn(){
			console.log(this)
		}
		fn()  // windwo

被嵌套的函数独立嵌套调用

		 var name = "summer";
        var person = {
            name : "zwj",
            sayName:function(){
                function test(){
                    console.log(this.name); //summer
                }
                test();
            }
        }
        person.sayName();
        //=================================
        // 等同于下方的立即执行函数
        var name = "summer";
        var person = {
            name : "zwj",
            sayName:function(){
                (function test(){
                    console.log(this.name); //summer
                })()
                // test()
            }
        }
        person.sayName();

闭包

var name = "summer";
        var person = {
            name : "zwj",
            sayName:function(){
                // 闭包的this指向是window 此时可以使用变量将this保存下来
        	    // var that = this;
                return function test(){
                    console.log(this.name);  // summer
                    // console.log(that.name);  // zwj
                }
            }
        }
        console.log(person.sayName())
        //test(){
        //    console.log(this.name); 
        // }

        console.log(person.sayName()())
        // summer

二、隐式绑定

被直接对象所包含的函数调用时,也称为方法调用,this隐式绑定到该直接对象

        // 隐式绑定 this指向调用对象
        var people = {
        	name:"zwj",
        	age:18,
        	detail(){
        		console.log(this)
                console.log('姓名:'+this.name)
                console.log('年龄:'+this.age)
        	}
        }
        people.detail()

隐式丢失

函数别名

隐式丢失是指被隐式绑定的函数丢失绑定对象,从而默认绑定到window

		var name ="summer"
        var age =50
        var people = {
        	name:"zwj",
        	age:18,
        	detail(){
                console.log('姓名:'+this.name)
                console.log('年龄:'+this.age)
        	}
        }
        
        var other = people.detail
        other()
		 // ============================
		// 等同于下方代码部分
		var other = detail(){
                console.log('姓名:'+this.name)
                console.log('年龄:'+this.age)
        }
        other()
传递参数
		var a = 0;
		function foo(){
		    console.log(this.a);
		};
		function bar(fn){
		    fn();
		}
		var obj = {
		    a : 2,
		    foo:foo
		}
		//把obj.foo当作参数传递给bar函数时,有隐式的函数赋值fn=obj.foo。与上例类似,只是把foo函数赋给了fn,而fn与obj对象则毫无关系
		bar(obj.foo);//0

三、显式绑定

通过call()、apply()、bind()方法把对象绑定到this上

        // 硬绑定
        var person = {
        	name:"zwj",
        	age:18,
        	sayName(){
        		console.log('我的名字是:'+this.name)
        	}
        }
        var personOne = {
        	name:"Henry"
        }
        var personTwo = {
        	name:"Bucky"
        }
        // 使用call、apply绑定this的指向
        person.sayName.call(personOne) // 我的名字是:Henry
        person.sayName.call(personTwo) // 我的名字是:Bucky

        person.sayName.apply(personOne) // 我的名字是:Henry
        person.sayName.apply(personTwo) // 我的名字是:Bucky

四、构造函数绑定

        // 构造函数绑定
        function showPerson(name){
        	this.name = name
        	this.sayName = function(){
        		console.log('我的名字是:'+this.name)
        	}
        }
        var name = 'Summer'
        var Bingo = new showPerson('Bingo')
        Bingo.sayName() // 我的名字是:Bingo

五、严格模式

严格模式下,独立调用的函数的this指向undefined

		function fn(){
		    'use strict';
		    console.log(this);//undefined
		}
		fn();
		
		function fn(){
		    console.log(this);//window
		}
		fn();

练习

		function a(){
        	function b(){
        		// 没有明确指明调用的对象 默认绑定 全局 window
        		console.log(this)
        		function c(){
        			"use strict";
        			// 严格模式下 undefined
        			console.log(this)
        		}
        		c()
        	}
        	b()
        }
        a()
        var name = "小白"
        function special(){
        	console.log('姓名3:' + this.name) // 小红
        }
        
        var person = {
        	name:'小红',
        	detail(){
        		console.log('姓名1:'+this.name) // 小红
        	},
        	other:{
        		name:'小黄',
        	    detail(){
        		    console.log('姓名2:'+this.name) // 小黄
        	    }
        	},
        	special:special
        }
        
        // 隐式绑定 this指向调用对象 person调用detail方法
        person.detail()
        person.other.detail()
        // person调用special方法 this指向person对象 调用person对象的name
        person.special()
		var name = "小红"
        function a(){
        	var name = "小白"
        	console.log('姓名1:'+this.name)
        }

        function d(i){
        	return i()
        }

        var b = {
        	name:"小黄",
        	detail(){
        		console.log('姓名2:'+this.name)
        	},
        	bibi(){
        		return function(){
        			console.log('姓名3:'+this.name)
        		}
        	}
        }

        var c = b.detail;
        b.a = a
        var e = b.bibi()

        // 全局调用a方法(window)、this.name = 小红
        a()
        
        // 因为前面  var c = b.detail; 所以此时相当于 c 就相当于只是个函数  detail(){} 全局 this.name = 小红
        c()

        // 此时就是b调用了方法 a 此时的this指向b this.name = 小黄
        // var b = { a:function(){var name = "小白" console.log('姓名1:'+this.name)}}
        b.a() 

        // d函数内部传递过去 b.detail 直接执行b.detail 全局下的d调用 this.name = 小红
        d(b.detail)

        // 因为  var e = b.bibi() 所以此时的e() = function(){console.log('姓名3:'+this.name) } 全局调用 所以 this.name =小红
        e()
		var name = 222
        var a = {
        	name:111,
        	say:function(){
        		console.log(this.name)
        	}
        }
        var fun = a.say  // fun 赋值 a.say的方法
        fun() // 222  全局调用 指向window
        a.say() // 111 // 谁调用 指向谁 a.name = 111

        var b = {
        	name:333,
        	say:function(fn){
        		fn()
        	}
        }
        b.say(a.say) //222 立即执行函数 指向window
        b.say =a.say // 将a的say方法 赋值给b的say方法
        b.say() // 333 谁调用 指向谁 b.name = 333

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值