Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Day18 - 介绍一下this指向4种形式 #61

Open
su37josephxia opened this issue Jan 18, 2022 · 25 comments
Open

Day18 - 介绍一下this指向4种形式 #61

su37josephxia opened this issue Jan 18, 2022 · 25 comments

Comments

@su37josephxia
Copy link
Owner

su37josephxia commented Jan 18, 2022

@bianzheCN
Copy link

四种形式

bind, apply, call, new

bind

指定函数执行时的 this

apply

指定函数执行时的 this 并调用函数

call

指定函数执行时的 this 并调用函数,跟 apply 的区别在于,从第二位起是函数的参数,而 apply 会把第二个数组参数的所有元素作为函数参数

new

在调用构造函数的时候将 this 指向创建的空对象

@wzl624
Copy link

wzl624 commented Jan 18, 2022

  1. 如果是一般函数,this指向全局对象window;
  2. 在严格模式下"use strict",为undefined.
  3. 对象的方法里调用,this指向调用该方法的对象.
  4. 构造函数里的this,指向创建出来的实例.

@partiallove
Copy link

第一、如果一个函数中有this,但是它没有以对象方法的形式调用,而是以函数名的形式执行,那么this指向的就是全局对象;
第二、如果一个函数中有this,并且这个函数是以对象方法的形式调用,那么this指向的就是调用该方法的对象;
第三、如果一个函数中有this,并且包含该函数的对象也同时被另一个对象所包含,尽管这个函数是被最外层的对象所调用,this指向的也只是它上一级的对象,

如:

var  obj = {
test;{
fun:function(){
console.log(this);
      }
   }
}

obj.test.fun();

第四、如果一个构造函数或以类方法中有this,那么它指向该构造函数或类创建出来的实例对象。

@zzzz-bang
Copy link

zzzz-bang commented Jan 18, 2022

默认绑定
如果是一般函数,this指向全局对象window,在严格模式下"use strict",为undefined.
隐式绑定
对象的方法里调用,this指向调用该方法的对象.
显式绑定
对于call、apply、bind的这三种调用方式都是属于显式绑定,作用是通过显示传入一个对象,改变this的上下文为此对象。call和apply是直接改变上下文对象直接调用,而bind是返回一个已经显示绑定的上下文的函数
new绑定
构造函数里的this,指向创建出来的实例.
一般情况下:new绑定 > 显式绑定 > 隐式绑定 > 默认绑定

@674252256
Copy link

_Rainbow_Z:
⾸先,在默认情况下,this是指向全局对象的,⽐如在浏览器就是指向window。
其次,如果函数被调⽤的位置存在上下⽂对象时,那么函数是被隐式绑定的。
再次,显示改变this指向,常见的⽅法就是call、apply、bind,由于bind将obj绑定到f函数上后返回⼀个新函数,因此需要再在后⾯加上括号进⾏执⾏,这是bind与apply和call的 区别

_Rainbow_Z:
最后,也是优先级最⾼的绑定 new 绑定。 ⽤ new 调⽤⼀个构造函数,会创建⼀个新对象, 在创造这个新对象的过程中,新对象会⾃动绑定到Person对象的this上, 那么 this ⾃然就指向这个新对象。

_Rainbow_Z:
绑定优先级: new绑定 > 显式绑定 >隐式绑定 >默认绑定

@zcma11
Copy link

zcma11 commented Jan 18, 2022

  1. 一般的函数调用情况下,this指向全局。这是因为直接从内存中找到这个函数然后拿出来的时候,没有绑定所处的环境,所以采用默认的全局对象作为 this。

  2. 对象方法调用,obj.foo() ,这时候根据在对象属性里得到的函数的地址值来访问这个函数,这个函数拿出来的时候环境是处在这个对象内,所以 this 指向这个对象。

  3. new 创建实例的时候,this 指向的是这个实例。

  4. call,apply,bind 绑定 this,这时候 this 指向提供的对象。

@Limeijuan
Copy link

a.如果是一般函数,this指向全局对象window;

b.在严格模式下"use strict",为undefined.

c.对象的方法里调用,this指向调用该方法的对象.

d.构造函数里的this,指向创建出来的实例.

@chunhuigao
Copy link

  • 默认情况this指向window,严格严格模式下指向undefined
  • 对象调用时,只想当前对象
  • 被call、apply、bind改变时,只想改变的对象
  • 通过new创建新对象时默认指向新创建的对象

@qytayh
Copy link

qytayh commented Jan 18, 2022

结论

  • 如果是一般函数,this指向全局对象window;
  • 在严格模式下"use strict",为undefined.
  • 对象的方法里调用,this指向调用该方法的对象.
  • 构造函数里的this,指向创建出来的实例

改变this指向的方法

改变this的指向并且执行调用函数
.call(), call(thisScope, arg1, arg2, arg3...)
.apply(), apply(thisScope, [arg1, arg2, arg3...]);两个参数

而bind 改变this的指向,返回的是函数
.bind() bind(thisScope, arg1, arg2, arg3...)

@QbjGKNick
Copy link

this指向的四种情况:

  • new,通过new构造函数里的this,指向新创建的实例
  • call、apply、bind绑定this,this指向传递的对象;
  • 默认情况下,全局上下文中this指向window,如果在严格模式时,this为undefined
  • 方法执行时,通过.调用方法,则方法中的this指向该对象

@superjunjin
Copy link

一,判断this指向原则

函数中的this,指向函数运行时所在的对象(当前对象,而不是上层对象)。如果函数运行时没有依赖的当前对象,则this指向最上层对象(eg: window)。

二,this指向的几种情况

1. obj.fun()中的this,指向当前运行的对象obj

fun 中的 this->obj ,自动指向.前的对象

var obj ={
   foo: function () {
     console.log(this);
   }
 };
 
 obj.foo() // obj

2. new Fun()中的this,指向当前运行的对象(new出来的新实例对象)

Fun 中的 this->正在创建的新对象,new 改变了函数内部的 this 指向,导致 this 指向实例化的对象

function Person(name) {
  this.name = name;
  console.log(this); // Person {name: "song"}
};

var person = new Person('song');
console.log(person.name);// "song" 

3. fun()中的this,指向当前运行的对象window

this->最上层对象(eg: window),直接执行函数,this指向默认的最上层对象(eg: window)

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

4. 函数中的函数的this,没有依赖的当前对象,默认指向window

this->最上层对象(eg: window),因为函数内函数,没有调用它的对象,所以只能指向默认的额window。

  • 例1,函数中的赋值型函数
 var o = {
   f1: function () {
     console.log(this);
     var f2 = function () {
       console.log(this);
     }();
   }
 }
 
 o.f1()
 // Object
 // Window (没有调用的它的对象了,所以只能指向默认的额window)

@yaoqq632319345
Copy link

this指向的4种形式按优先级来说分别为

  1. new 关键字 this指向新创建的对象
  2. call,apply,bind绑定时,this指向绑定的对象
  3. 通过对象调用方法时,this指向调用方法的对象
  4. 没有调用对象时,指向全局

@792472461
Copy link

  1. 独立函数调用,例如getUserInfo(),此时this指向全局对象window
  2. 对象调用,例如stu.getStudentName(),此时this指向调用的对象stu
  3. call()、apply()和bind()改变上下文的方法,this指向取决于这些方法的第一个参数,当第一个参数为null时,this指向全局对象window
  4. 箭头函数没有this,箭头函数里面的this只取决于包裹箭头函数的第一个普通函数的this
  5. new构造函数调用,this永远指向构造函数返回的实例上,优先级最高。

@alec1815
Copy link

当默认情况 this 指向 window 但严格模式下指向 undefined
当对象调用时指向当前对象
被call、apply、bind改变指向改变的对象
通过new创建新对象时新创建的对象
new -> call、apply、bind -> 对象调用 -> 默认情况

@alienRidingCat
Copy link

alienRidingCat commented Jan 18, 2022

● web全局环境下的this指向window,nodejs环境为global对象
● 非严格模式下,函数内部的this指向window,严格模式下,为undefined
● 对象的方法里调用,this指向调用该方法的对象 。被嵌套的函数独立调用时,this默认指向window
● 构造函数里的this,指向创建出来的实例
● 此外,bind/call/apply 可以更改绑定this的指向

@JanusJiang1
Copy link

JanusJiang1 commented Jan 18, 2022

this 绑定有四条规则

默认绑定,隐式绑定,显示绑定,new绑定

this 是在函数被调用时才会绑定的,所以要确定函数中this绑定,我们首先需要找到函数的调用位置。
然后再根据以上四条规则,按照其优先级 new绑定>显示>隐式>默认 ,就能确定this 的绑定对象。

默认绑定

函数被直接调用,不符合其他三条绑定规则则会默认绑定,非严格模式下this指向全局对象,严格模式下指向undefined

function foo( ){
  console.log( this.a )
}
var a =1 ;
foo( );//1
function foo( ){
"use strict"
  console.log( this.a )
}
var a =1 ;
foo( );// TypeError: this is undefined

隐式绑定

调用位置有上下文对象,或者说调用函数被某个对象拥有或者包裹。引用到了对象的属性上,然后通过对象调用。
this会指向这个对象

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

obj的foo属性,指向了foo函数,通过obj.foo()调用,this指向了obj。

  • 隐式丢失

但这里要注意,隐式丢失的情况,就是因为obj.foo其实也指向foo函数的引用,这个引用如果被赋值给另一个变量,再通过该变量调用,那就相当于跳过了obj,直接调用了,所以会造成隐式丢失。

function foo( ){
  console.log( this.a )
}
var obj={
   a:1,
  foo:foo
} ;
var b=obj.foo;
b( ); // TypeError: this is undefined

以上,相当于全局直接调用foo函数,所以是默认绑定。
注意,函数作为参数传参给别的函数,也是一种隐式赋值,一样会发生隐式丢失的情况。

显示绑定

通过,apply(...),call(...) ,bind( )硬绑定,修改this指向

function foo( ){
  console.log( this.a )
}
var obj={
   a:1
} ;
foo.call(obj); //1
foo.apply(obj); //1

var bar=foo.bind(obj);
bar(3);//1

bind其实就是基于包裹了一层函数,内部再通过apply实现的硬绑定,解决上面说的this丢失问题,这章暂不细纠。

以上代码都将,foo中this指向了obj。

new

通过new的方式来调用函数,会创建一个新的实例对象,构造函数中的this也会指向这个新创建的对象。
new的方式改变this指向的优先级式最高的。

function foo( a){
  this.a=a;
}
var b= new foo(2);
console.log(b.a);//2

总结

以上,我们知道了确认this绑定,需要知道调用位置,再按优先级从高到低,ew绑定>显示>隐式>默认,看匹配哪条规则,就能明确this指向。

@aiuluna
Copy link

aiuluna commented Jan 18, 2022

  • 方法调用模式,当一个函数作为一个对象的属性被调用,this指向该对象
var myObject = {
	name: 'myobj',
  myFunc: function() {
  	console.log(this.name) // myobj
  }
}
myObject.myFunc()
  • 函数调用模式,当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的。当这个函数被调用时,this绑定到全局对象
var name = 'window';
var myObject = {
	name: 'myobj',
  myFunc: function () {
  	console.log(this.name) // myobj 方法调用模式
  	var func = function() {
    	console.log(this.name) // window, 函数调用模式
    }  
    func()
  }
}

myObject.myFunc()
  • 构造器调用模式,当一个函数使用new新建实例时,会将新创建的实例对象指向构造器函数的prototype,并且this指向该实例对象
var myObject = function(name) {
	this.name = name
}
myObject.prototype.myFunc = function(){
	console.log(this.name)
}

var obj = new myObject('objname');
obj.myFunc()  // objname
  • apply, call, bind调用模式,第一个参数会传递this指向的对象
var name = 'window'
var obj = {
	name : 'obj'
}
var myFunc = function(){
	console.log(this.name)
}
myFunc()   // window
myFunc.bind(obj)() // obj
myFunc.apply(obj) // obj
myFunc.call(obj) // obj

@jiafei-cat
Copy link

全局上下文的this

严格/非严格模式全局上下文的this都指向window

函数上下文的this

场景 this指向
普通函数调用 严格模式默认指向undefined/非严格模式默认指向window
对象中的函数调用模式 默认指向调用的对象
call/apply/bind 调用模式 默认指向第一个参数
构造函数调用模式(new) 如果构造函数没有返回对象,就指向新对象,否则指向构造函数返回的对象
箭头函数调用模式 this指向上层非箭头函数的this

不同调用this的优先级

new 调用 > call/apply/bind > 对象上的函数调用 > 普通函数调用

@yanzefeng
Copy link

1.如果是一般函数,this指向全局对象window;
2.在严格模式下"use strict",为undefined.
3.对象的方法里调用,this指向调用该方法的对象.
4.构造函数里的this,指向创建出来的实例.

@863379105
Copy link

@ruixue0702
Copy link

this 对象是在运行时基于函数的执行环境绑定的
在全局函数中,this 指向 window,而当函数被作为某个对象的方法调用时,this 指向那个对象。
匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window。
箭头函数中没有this,this指向其所处的词法作用域
普通函数,在严格模式下为undefined

@crazyyoung1020
Copy link

crazyyoung1020 commented Jan 18, 2022

this指向,也即this绑定的4种形式如下:

  1. 默认绑定,指向window。在全局环境下的this指向window;普通函数定义后,执行时内部的this也指向window;回调函数内部,this也指向window;箭头函数例外,其内部this是定义它的环境下的this指向。
console.log(this); // window;

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

setTimeout(function(){
    console.log(this); // window
},1000)
  1. 隐式绑定,指向调用函数的对象,如,对象内有函数属性,调用该函数,则this指向该对象。
let obj = {
    foo:function(){
        console.log(this); // obj
    }
}
obj.foo()
  1. 显示绑定,通过call、apply或bind去修改this的指向,如下
function foo(){
    console.log(this.a)
}
let obj = {
    a:1
}

foo.call(obj);// 1
  1. new 构造函数绑定,通过new 构造函数创建一个新的实例,将构造函数内的this指向该实例,如下
function Dog(options){
    this.name = options.name;
    this.age = options.age;
}

dog1 = new Dog({name:'dog1',age:'1'})
console.log(dog1.name); // dog1
console.log(dog1.age); // 1

dog2 = new Dog({name:'dog2',age:'2'})
console.log(dog2.name); // dog2
console.log(dog2.age); // 2

@zhenyuWang
Copy link

结论

  • 如果是一般函数,this 指向全局对象 window
  • 在严格模式下(use strict),为 undefined
  • 对象的方法里调用,this 指向调用该方法的对象
  • 构造函数里的 this,指向创建出来的实例

改变 this 指向的方法

call

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

func.call(thisScope, arg1, arg2, arg3...)

apply

apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

func.apply(thisScope, [arg1, arg2, arg3...])

bind

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

func.bind(thisScope, arg1, arg2, arg3...)

@rachern
Copy link

rachern commented Jan 18, 2022

  1. 如果是普通函数,this 指向全局对象,在浏览器是 window,在 node 是 global
  2. 如果是箭头函数,this 指向定义时外部环境的 this
  3. 如果是对象调用,则 this 指向该对象
  4. 如果是在构造函数或者Class中, this 指向构造出来的实例
  5. 如果是使用 bind、call、apply,this 指向函数的第一个值对应的对象
  6. 如果是在严格模式下,this 在函数外部指向 全局,在函数内部指向 undefined

@su37josephxia su37josephxia changed the title 介绍一下this指向4种形式 Day18 - 介绍一下this指向4种形式 Jan 20, 2022
@rhythm022
Copy link

this 这四种指向性问题,其实说的是一个函数被调用的四种方式:

  • 一个函数可以作为函数被调用
  • 可以作为方法被调用
  • 可以作为构造函数被调用
  • 也可以用call apply bind的方式去调用。

这四种调用方式会造成的是会有不同的this指向。如果你是用函数的方式去调用,那么this在严格模式下就是undefined,在普通模式下就是window。如果你是用方法的方式去调用,那么 this 指向的就是这个方法所属的那个对象。如果你是用构造函数去调用,那么this就是一个空对象。如果你是用call apply bind去调用,那么就是你指定this的值了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests