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()

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

相关推荐
FogLetter3 分钟前
深入浅出React Hooks:useEffect那些事儿
前端·javascript
Savior`L3 分钟前
CSS知识复习4
前端·css
0wioiw018 分钟前
Flutter基础(前端教程④-组件拼接)
前端·flutter
花生侠43 分钟前
记录:前端项目使用pnpm+husky(v9)+commitlint,提交代码格式化校验
前端
一涯1 小时前
Cursor操作面板改为垂直
前端
我要让全世界知道我很低调1 小时前
记一次 Vite 下的白屏优化
前端·css
1undefined21 小时前
element中的Table改造成虚拟列表,并封装成hooks
前端·javascript·vue.js
蓝倾2 小时前
淘宝批量获取商品SKU实战案例
前端·后端·api
comelong2 小时前
Docker容器启动postgres端口映射失败问题
前端