JavaScript 带你理解this关键字

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

为什么要有this ?

  • this 提供了一种更优雅的方式来隐式的传递一个对象的引用,可以让代码更加简洁利于复用
js 复制代码
//需要给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
  • 块级作用域?不不没有它,只有上面两个,为什么?
js 复制代码
//块级
{
  let a = this;
  console.log(a);
}

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

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

this的绑定规则

1.默认绑定---当函数 被独立调用时 ,函数的this默认指向到window

(即使this是在函数体里的,但是被独立调用,仍然会指向全局的window)

js 复制代码
// 代指:
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全局的,代码都在浏览器上执行

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

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

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

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

2.隐式绑定---当函数引用有上下文对象且被该对象调用时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象

什么是函数引用 是指foo()不带() 的 foo

js 复制代码
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会指向最近的那一层对象

js 复制代码
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接收参数

js 复制代码
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.prototype call将this指向obj ,并且帮忙接收foo参数和调用foo函数

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

js 复制代码
foo.apply(obj,[1,2])//区别

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

js 复制代码
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绑定到实例对象上

js 复制代码
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

js 复制代码
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的

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

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

相关推荐
纪伊路上盛名在几秒前
jupyter内核崩溃
前端·数据库·jupyter·生物信息·基因组·k-mer
Net蚂蚁代码1 小时前
Angular入门的环境准备步骤工作
前端·javascript·angular.js
小着4 小时前
vue项目页面最底部出现乱码
前端·javascript·vue.js·前端框架
lichenyang4536 小时前
React ajax中的跨域以及代理服务器
前端·react.js·ajax
呆呆的小草6 小时前
Cesium距离测量、角度测量、面积测量
开发语言·前端·javascript
一 乐7 小时前
民宿|基于java的民宿推荐系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·源码
testleaf8 小时前
前端面经整理【1】
前端·面试
好了来看下一题8 小时前
使用 React+Vite+Electron 搭建桌面应用
前端·react.js·electron
啃火龙果的兔子8 小时前
前端八股文-react篇
前端·react.js·前端框架
小前端大牛马8 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js