15年软件开发经验 只做源码定制 互联网+定制化解决方案

15年软件开发经验,只做源码定制!

原创设计 定制开发

满足您的个性化需求

当前位置:首页 前端开发 js

javascript的this指向

梁鹏翱| 发布于 2021-11-18 17:41:18| 573阅读| 0点赞| 0评论
举报

js的this指向

接触js这么久,经常因为this指向问题头疼,前两天我在网上好好了解了一下this,并整理了相对来说比较易懂的讲解,希望能有帮助!

this的那些绑定规则

常见的绑定规则有如下四种:

  1. 默认绑定
  2. 隐式绑定
  3. 显示绑定
  4. new 绑定
   接下来让我们好好说道说道。

默认绑定

什么是默认绑定?默认绑定不就是什么处理都不做的时候的绑定规则吗?很显然就是我们直接调用函数的时候,这时候就是默认绑定。不需要多说,默认绑定的this就是window

全局调用全局函数

在全局定义的函数,直接调用,很明显绑定的是window

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

// window
foo()

函数内调用全局函数

在全局定义的函数,如果在其他函数内调用,那么this是绑定的是那个对象?肯定还是window了,毕竟函数还是直接调用嘛。

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

隐式绑定

隐式绑定就是通过对象的形式调用函数。其实也可以说是调用方法,因为这些函数都是定义在对象上的。当然方法只是函数在不同位置的叫法而已,这里不需要纠结。

比如我们定义对象obj,并在上面定义方法(函数)foo。那么通过对象obj调用函数foo,绑定的this的值会是????

var obj = {
	name: "zs",
    foo: function(){
        console.log(this);
    }
}
// ?
obj.foo(); // obj

当然隐式绑定的this的值是对象obj了。那么结果显而易见,隐式绑定的优先级是大于默认绑定的。

而隐式绑定调用的函数的this的指向可以理解为,谁调用,this就指向谁。之所以我们说是叫做隐式绑定,是因为我们没有在函数上直接绑定this的值是xxx对象。

显示绑定

显示绑定就是显示的告诉函数,我要绑定this的值是xxx对象。

全局函数显示绑定this

定义的全局函数,如果在执行的时候,直接显示的绑定this的值,那么很显然,this的值肯定是我们手动绑定上去的喽!

function foo(){
      console.log(this);
    }
foo(); // window
foo.call("123"); // '123'
foo.apply(123); // 123
foo.bind({name:"zzz"})(); // {name: "zzz"}

结果可以证明: 显示绑定的this的优先级是大于默认绑定规则的。

那么接下来我们应该比较一下显示绑定和隐式绑定的优先级。

对象的方法(函数)显示绑定this

我们定义一个对象,并对该函数的方法进行显示的绑定,看其中的this是指向哪里的。

 var obj = {
     name: "zs",
     foo: function () {
         console.log(this);
     }
 }
obj.foo.call("123"); // '123'
obj.foo.apply("123"); // '123'
obj.foo.bind("123")(); // '123'

通过取出对象obj的方法foo,然后对其进行显示的this绑定,我们发现结果是:this的指向是我们显示绑定的对象。

那么这样是否就证明了:显示绑定的优先级就一定大于隐式绑定?其实不然,我们通过对象.方法名的形式,已经是直接取出了这个定义在方法中的函数的引用,接下来进行该函数的显示绑定,严格来说已经和对象obj没有关系了。

var obj = {
      name: "zs",
      foo: function () {
        console.log(this);
      }
    }
    var fn = obj.foo;
    fn(); // window

可以看见,取出了对象中定义的函数,然后在进行调用,可以对比函数直接定义在全局中,然后通过默认绑定规则的调用该函数,所以最终this也是绑定在全局对象window上的。

那么,我们要如何证明显示绑定和隐式绑定的优先级的大小呢?

我们的目的就是进行显示的绑定this,且隐式的调用这个显示绑定的函数,这样最终的this指向,就可以证明出我们两种方式的优先级了。

我们实现定义好函数,然后定义对象obj,且将定义好的全局函数通过显示的绑定this的值,然后将这个显示绑定好this的函数赋值给obj对象的foo属性。最后通过obj.foo()调用该函数,就知道显示绑定和隐式绑定的优先级了。

function foo(){
    console.log(this);
}
var obj = {
    name: "zs",
    foo: foo.bind("123")
}
obj.foo(); // "123"

根据结果,我们可以知道,显示绑定this的优先级肯定是大于隐式绑定的。

new 绑定

new绑定,其实就是通过构造函数创建对象。当我们new的时候,会创建一个空对象,且将空对象的引用赋值给构造函数的this,这样this就会指向这个空对象,且会在构造函数的最后,如果没有返回值,自动帮我们返回这个this。

写成伪代码大概就是:

function Person(name,age){
	this.name = name;
    this.age = age;
    // 不需要我们返回this
    return this;
}

new绑定需要的函数是构造函数,构造函数没有显示指定的返回值,且构造函数一般首字符是大写。

function Person(name,age){
    this.name = name;
    this.age = age;
}
var person = new Person("zs",21);
console.log(person);


new 绑定,其中的this的指向就是我们通过new关键字创建出来的空对象。然后通过构造函数给这个空对象添加各种属性。

ES6的箭头函数 arrow function

箭头函数是ES6之后新增的编写函数的方法,写法比函数表达式更加简洁。

特点:

  1. 箭头函数不会绑定this,arguments属性;
  2. 箭头函数不能作为构造函数来使用(说白了就是不能搭配new使用);
箭头函数不使用上面的this的四种规则,通俗的说就是不绑定this,而是根据外层作用域来决定this的指向。
var foo = () => {console.log(this)}
// 均为 window
foo();
foo.call("123");
var obj = {
    name: "zs",
    foo: foo
};
obj.foo();
0

0条评论

别默默看啦~登录/注册一起参与讨论吧~

热门标签

梁鹏翱
微信扫一扫立即咨询
账号登录|扫码登录

立即注册 |忘记密码?

欢迎注册

已有账号马上登录

重置密码

扫码绑定微信
微信扫一扫

绑定手机号

分享到-微信

举报

  • 举报类型:

  • 举报描述:

您好,当前积分不足。

在线客服
拨打电话
17330196230 13230981129
顶部