当前位置:首页 > JavaScript > 正文

JavaScript中this的用法

前言 本篇文章将讲到之前new原理中的为讲到的call()方法

为什么要有this ?

this 提供了一种更优雅的方式来隐式的传递一个对象的引用,可以让代码更加简洁利于复用

//需要给speek和identify显示传入一个上下文对象
function identfy(context) {
  return context.name.toUpperCase(); //英文大写
}
function speak(context) {
  var greeting = "hello ,I'm " + identfy(context) + ",I hate Trump!";
  console.log(greeting);
}

var me = {
  name: "",
};
speak(me);



function identfy1() {
  return this.name.toUpperCase(); // toUpperCase(); //英文大写
}
function speak1() {
  var greeting = "hello ,I'm " + identfy1.call(this) + ",I love China!";
  console.log(greeting);
}

var me1 = {
  name: "Donald Trump",
};
speak1.call(me1); //调用的时候

this可以使用在哪里?

函数作用域:全局作用域:默认this指向的是window

块级作用域?不不没有它,只有上面两个,为什么?

//块级
{
  let a = this;
  console.log(a);
}

来,你看这段代码,块级作用域是指let的变量和{}一起是块级,那么这this就不是在块级里面了,实则是在全局window上哦

this是一个代词,它代指一个对象

this的绑定规则

1.默认绑定---当函数  被独立调用时 ,函数的this默认指向到window (即使this是在函数体里的,但是被独立调用,仍然会指向全局的window)

// 代指:
var a = 1; //挂在window
function foo() {
  console.log(this.a);//this是在foo里面的,但它指向的是window
}
function Bar() {
  var a = 2;
  foo();//独立调用
}
Bar();

要在浏览器上才能看到挂在windowd的上的a,编译器上运行node结果是undefined,所以后续要用到window全局的,代码都在浏览器上执行

独立调用是什么?没有其他前缀的调用

var obj = { a: 1 ,
  foo: function () {
    console.log(this);
  }//不是独立调用
};
obj.foo();

这段代码就不是独立调用 有obj去调用它

在来看下面这段代码:同理因为是独立调用触发的是默认绑定,绑定在window,全局上,所以this是函数作用域外面的全局作用域

2.隐式绑定---当函数引用有上下文对象且被该对象调用时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象 什么是函数引用  是指foo()不带() 的    foo

var a = 1;
function foo() {
  console.log(this.a);
}


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



var obj = {
  a: 2,
  foo: foo, //foo引用 来找找到函数
};
obj.foo();



var obj = {
  a: 2,
  foo: foo(),
};
obj.foo(); //报错
obj.foo

第一个obj与第二个obj是等同的,单写foo是指引用,v8执行时会去找foo变量或者函数,这里没有变量就会找到函数foo

第三种写法是错误的,foo()加了括号这里就是调用函数,而这里的函数没有返回值,这里的值就是undefin,那么foo:undefined,而后在对象外面调用的话,obj.foo(),是调用名为foo的函数,但这里foo:undefined值是undefined不是函数体,所以会报错,如果是obj.foo的话是指对象的一个属性,属性名为foo,并且这里没有做任何操作,也不会报错。

3.隐式丢失---当一个函数被多层对象调用时,函数的this会指向最近的那一层对象

var a = 1;
function foo() {
  console.log(this.a);
}


var obj = {
  a: 2,
  foo: foo, //foo引用
};

var obj2 = {
  a: 3,
  obj:obj
   
};
obj2.obj.foo();

函数的this会指向最近的那一层对象即obj而不是obj2

4.显示绑定

1.fn.call(obj,x,y,....)显示的将fn里面的this绑定到obj对象上,并且call帮fn接收参数

function foo(x,y){
  console.log(this.a,x+y);

}
var obj={
  a:2
}
foo.call(obj,1,2)//显示绑定
foo.call(1,1,2)//如果第一个参数不是对象,默认给一个null
foo.call(null,1,2)//显示绑定

call方法是定义在Funtion.prototype上的foo.prototype.__proto__===Function.prototypecall将this指向obj ,并且帮忙接收foo参数和调用foo函数

2.fn.apply(obj,[x,y,....])显示的将fn里面的this绑定到obj对象上,并且apply帮fn接收参数,参数必须以数 组的形式盛放

foo.apply(obj,[1,2])//区别

3.fn.bind(obj,x,y,....)(x,x, ....)显示的将fn里面的this绑定到obj对象上,并且bind会返回一个新的函数,bind和新函数都可以负责帮fn接收参数,参数零散的传入

const bar=foo.bind(obj,1,2)//
bar()
const bar1=foo.bind(obj)
bar1(1,2)
const bar3=foo.bind(obj,2,4)
bar3(1)

bind会返回一个新的函数体,但是我们要自己触发这个函数,才能接着触发foo的函数

5.new绑定  --new 的原理会导致函数的this绑定到实例对象上

function Person() {
  //var obj = {};
  //Person.call(obj);
  this.name = "特朗普";
  this.age = 18;
  console.log(this);
  //obj.__proto__ = Person.prototype;
  //return obj;
}
const p1 = new Person();

因为new的过程使用了call()方法将将Person的this指向obj,最后将obj返回给实例对象,即即把Person的this绑定到了实例对象上

箭头函数

箭头函数中没有this这个概念,写在了箭头函数的中的this,也是它外层那个非箭头函数的this

function a() {
  console.log(this);
  let b = function () {
    let c = () => {
      let d = () => {
        console.log(this);//箭头函数里面没有this这个关键字
      };
      d();
    };
    c();
  };
  b();
}
a();

这的this是在fuction a(){} 里面的,但不指向funtion a(){},因为默认绑定规则,所以是指向window的

var a = 1
var obj = {
  a: 2,
  bar: function() {
    const baz = () => {
      console.log(this.a);
    }
    baz()
  }
}
obj.bar()

如有错误欢迎指正,欢迎各位友友评论点赞!


有话要说...