this学习总结10

函数预编译过程 this->window
全局作用域 this->window
call/apply 改变函数运行时this指向
obj.func() func里面的this指向obj

函数执行,this指向才有意义,
每一次函数执行,就会产生一个this指向

默认绑定规则 函数的独立调用 this指向window
隐式绑定规则 作为对象方法调用,谁调用就指向谁;
显式绑定 call,apply,bind 改变this指向
new 绑定 指向实例化对象

箭头函数没有自己的this,可以拿父亲作用域中的this。它会捕获其所在(即定义的位置)的上下文的this值,作为自己的this值。

一、在独立的函数中使用 this 指代全局对象

在严格模式下,this指向undefined
非严格模式下,this指向window

function test(){
   this.x = 1
  console.log(this.x)
}
test();  // 1   this--->window
// 立即执行函数this都指向window
(function(){
	console.log(this); // window
})();

二、作为对象方法调用,this 指代上级对象

谁调用了这个方法,this就指向谁

var a=0;
var obj = {
    a:2,
    func1 : function() {
        console.log(this);
        function test(){
       		console.log(this);// window
        }
        test();
    }
}
obj.func1()  // this--->obj
var a=0;
var obj = {
    a:2,
    func1 : function() {
   		 console.log(this); // obj
        function test(){
        	console.log(this); // window
        }
        return test;
    }
}
obj.func1()()
// 相当于 obj.func1()-->test test()
var a=0;
function foo(){
	console.log(this)
}
var obj={
	a:2,
	foo:foo
}
obj.foo() // obj
var bar = obj.foo; 
bar()// window
// obj.foo 还没有执行 obj.foo=foo-->bar=foo-->bar执行
// 当方法被赋值的时候,会存在隐式丢失(变量赋值)
var a=0;
function foo(){
	console.log(this);
}
function bar(fn){
	fn();
}
var obj ={
	a:2,
	foo:foo
}
bar(obj.foo) // window
// fn-->obj.foo-->foo,fn是独立调用,所以foo是独立调用执行的
// 父函数有能力决定子函数的this指向
// 参数赋值

三、通过call,apply,bind

四、构造函数

  1. 在函数体最前面隐式的加上this = {}
  2. 执行this.xxx = xxx
  3. 隐式的返回this
function Person(){
	var this={};
	this.a=1;
	return this; // this指的是函数实例化之后的结果
	//return {}; // 值为引用值,会改变当前this指向,就不再指向实例化对象 
}
var person=new Person()

五、箭头函数

箭头函数的this指向是由外层函数的作用域决定的。

var a=0;
function foo(){
	var that=this;
	console.log(this); // obj
	var test=()=>{
		console.log(this); // obj
	}
	test();
}
var obj={
	a:1,
	foo:foo
}
obj.foo();

默认绑定规则(独立调用)对箭头函数无效

var a=0;
function foo(){
	console.log(this); // obj
	var test=()=>{
		console.log(this); // obj
	}
	return test;
}
var obj1={
	a:1,
	foo:foo
}
var obj2={
	a:2,
	foo:foo
}
obj1.foo()();

隐式绑定规则,无效

var obj1={
	a:1,
	foo:()=>{
		console.log(this); // window
	}
}
obj1.foo();

显式绑定,改变this指向无效

var a=0;
function foo(){
	console.log(this); // window
	var test=()=>{
		console.log(this); // window
	}
	return test;
}
var obj1={
	a:1,
	foo:foo
}
var obj2={
	a:2,
	foo:foo
}
foo().call(obj2);

new 不能实例化箭头函数

var foo=()=>{
	console.log(this); // 出错
}
new foo();

this的优先级

显式绑定优先级高于隐式绑定

function foo(){
	console.log(this.a);
}
var obj1 ={
	a:1,
	foo:foo
}
var obj2 ={
	a:2,
	foo:foo
}
obj1.foo(); // 1
obj2.foo(); // 2
obj1.foo.call(obj2); // 2
obj.foo.call(obj1); // 1

new绑定优先级高于显式绑定

function foo(b){
	this.a=b;
}
var obj1={};
var bar=foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2
var baz=new bar(3); // new 把this指向为baz
console.log(obj1.a); // 2
console.log(baz.a);  // 3

常见面试题

var name='222';
var a={
	name:'111',
	say:function(){
		console.log(this.name);
	}
}
var fun=a.say;//a.say代表这个function的函数引用
fun();//fun在全局范围内执行 ①   this---> window 222
a.say();//② this--->a  111
var b = {
	name:'333',
	say:function(fun){
		//这个方法里面的this--->b
		fun();
	}
}
b.say(a.say);//③  this--->window 222
b.say=a.say;//④
b.say();// this--->b 333

① 相当于function(){console.log(this.name);}放到全局作用域执行,跟谁调用它没关系,此时this指向window,打印222
②a调用say方法执行,谁调用this就指向谁,this指向a,打印111
③a.say相当于一个参数传进去了,

b.say(function(){
		console.log(this.name);
	})

b.say调用 this指向b,
参数在这个fun()里面执行,谁都没调用fun(),只是fun在b的say里面正常执行,空执行相当于走的预编译环节,(谁.fun(),这样fun里面的this才是谁) 所以this—>window,并没有说是this.fun();

var b = {
	name:'333',
	say:function(fun){
		function(){
			console.log(this.name);
		}
	}
}

④相当于

var b = {
	name:'333',
	say:function(){
			console.log(this.name);
	}
}
var name='window';
var obj1={
	name:'1',
	fn1:function(){
		console.log(this.name);
	}
	fn2:()=>console.log(this.name),
	fn3:function(){
		return function(){
			console.log(this.name);
		}
	},
	fn4:function(){
		return ()=>console.log(this.name);
	}
}
var obj2={
	name:'2'
}
obj1.fn1(); // 1
obj1.fn1.call(obj2); // 2

obj1.fn2(); // window
obj1.fn2.call(obj2); // window

obj1.fn3()(); // window
obj1.fn3().call(obj2); // 2
obj1.fn3.call(obj2)(); // window

obj1.fn4()(); // 1
// 箭头函数执行,找父作用域fn4 obj1调用fn4
obj1.fn4().call(obj2); // 1
// obj1.fn4() 是箭头函数,箭头函数的call 不改变this指向,
obj1.fn4.call(obj2)(); // 2
// obj1.fn4.call(obj2) 父作用域中的this指向了obj2
function Foo(){
	getName=function(){
		alert(1);
	}
	return this;
}
Foo.getName=function(){
	alert(2);
}
Foo.prototype.getName=function(){
	alert(3);
}
var getName=function(){
	alert(4);
}
function getName(){
	alert(5);
}
// 构造函数上的getName
Foo.getName(); // 2
// 全局上的getName被覆盖了
getName(); // 4
// Foo()执行后的getName被重新重写
Foo().getName(); // 1
// Foo执行完成被重写
getName(); // 1

new Foo.getName(); // 2
// new Foo()
new Foo().getName(); // 3
new new Foo().getName(); // 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值