JavaScript之this全面解析已经常见实例

栏目: JavaScript · 发布时间: 6年前

内容简介:this 关键字在 Javascript 中非常常见,但是很多开发者很难说清它到底指向什么。大部分人会从字面意思上去理解 this,认为 this 指向函数自身,实际上总结:函数被调用时发生 this 绑定,this 一共有 4 中绑定规则,接下来一一介绍每种规则的解释和规则直接的优先级

this 关键字在 Javascript 中非常常见,但是很多开发者很难说清它到底指向什么。大部分人会从字面意思上去理解 this,认为 this 指向函数自身,实际上 this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调 用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

总结:函数被调用时发生 this 绑定, this 指向什么完全取决于函数在哪里被调用

一、this 的绑定规则

this 一共有 4 中绑定规则,接下来一一介绍每种规则的解释和规则直接的优先级

  • 默认绑定(严格/非严格模式)
  • 隐式绑定
  • 显式绑定
  • new 绑定

1.1 默认绑定(严格/非严格模式)

  • 独立函数调用: 独立函数调用时 this 使用默认绑定规则,默认绑定规则下 this 指向 window(全局对象)
  • 严格模式下: this 无法使用默认绑定,this 会绑定到 undefined。

独立函数调用

function foo() {
  console.log(this.a);
}
var a = 2;
foo(); // 2
复制代码

严格模式下:

function foo() {
  "use strict";
  console.log(this); //undefined
  console.log(this.a); //Uncaught TypeError: Cannot read property 'a' of undefined
}
var a = 2;
foo();
复制代码

注意下边两种情况

var age = "18";
var obj = {
  name: "heyushuo",
  age: 25,
  fn: function() {
    function sayName() {
      console.log(this); //window
      console.log(this.age); //undefined
    }
    sayName();
  }
};
obj.fn();
复制代码

函数 sayName 虽然是在 obj.fn 内部定义的,但是它仍然是一个独立函数调用,this 仍然指向 window。

var a = "global";
var obj = {
  a: 2,
  foo: function() {
    console.log(this.a); //global
  }
};
var bar = obj.foo; // 函数别名!
bar();
复制代码

虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是函数本身,因此此时的 bar() 其实是一个不带任何修饰的独立函数调用,因此应用了默认绑定。

1.2 隐式绑定

当函数引用有上下文对象时(例如:obj.foo 这个时候使用 obj 上下文来引用函数 foo),隐式绑定规则会把函数中的 this 绑定到这个上下文对象。

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

obj.foo();
复制代码

对象属性引用链中只有上一层或者说最后一层在调用中起作用。

var obj = {
  name: "heyushuo",
  obj1: {
    name: "kebi",
    foo: function() {
      console.log(this.name); // kebi
    }
  }
};

obj.obj1.foo();
复制代码

隐式丢失被隐式绑定的函数会丢失绑定对象,而应用默认绑定,把 this 绑定到全局对象或者 undefined(严格模式) 上。 第一种

var a = "global";
var obj = {
  a: 2,
  foo: function() {
    console.log(this.a); //global
  }
};
var bar = obj.foo; // 函数别名!
bar();
复制代码

虽然 bar 是 obj.foo 的一个引用,但是实际上,它引用的是函数本身,因此此时的 bar() 其实是一个不带任何修饰的独立函数调用,因此应用了默认绑定。

第二种传入回调函数时:

var a = "global";
var obj = {
  a: 2,
  foo: function() {
    console.log(this.a); //global
  }
};
var bar = obj.foo; // 函数别名!
function doFoo(fn) {
  fn(); // <-- 调用位置!
}
doFoo(bar); //global

//和下边这种一样
setTimeout(obj.foo, 300);
复制代码

1.3 显示绑定

通过 call() 或者 apply()方法。第一个参数是一个对象,在调用函数时将这个对象绑定到 this 上,称之为显示绑定。

function foo() {
  console.log(this.a);
}
var obj = {
  a: 2
};
foo.call(obj); // 2
复制代码

显示绑定引申出来一个硬绑定,代码如下

function foo(something) { 
 console.log( this.a, something ); 
 return this.a + something;
}
// 简单的辅助绑定函数
function bind(fn, obj) { 
 return function() {
 return fn.apply( obj, arguments ); //内部已经强制绑定了传入函数this的指向
 };
}
var obj = { 
 a:2
};
var bar = bind( foo, obj ); 
var b = bar( 3 ); // 2 3
console.log( b ); // 5
复制代码

bar函数无论如何调用,它总会手动在 obj 上调用 fn,强制把 fn 的 this 绑定到了 obj。这样也解决前面提到的 丢失绑定问题

由于 硬绑定是一种非常常用的模式 ,所以在 ES5 中提供了内置的方法 Function.prototype.bind

function foo(something) { 
 console.log( this.a, something ); 
 return this.a + something;
}
var obj = { 
 a:2
};
var bar = foo.bind( obj );
var b = bar( 3 ); // 2 3 
console.log( b ); // 5
复制代码

1.4 new绑定

使用new来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。

  • 创建(或者说构造)一个全新的对象。
  • 这个新对象会被执行 [[ 原型 ]] 连接。
  • 这个新对象会绑定到函数调用的 this。
  • 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象。

例如:

function foo() { 
 this.name = "heyushuo";
 this.age = 25
} 
foo.prototype.sayName = function(){
  console.log(this.name+this.age);
}
var bar = new foo();

console.log(bar); //{name: "heyushuo", age: 25}
//这个新对象会绑定到函数调用的 this。所以此时的this就是bar对象
console.log( bar.age ); // 25
复制代码

如下图是 new foo() 这个对象

JavaScript之this全面解析已经常见实例

以上所述就是小编给大家介绍的《JavaScript之this全面解析已经常见实例》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Blockchain Basics

Blockchain Basics

Daniel Drescher / Apress / 2017-3-16 / USD 20.99

In 25 concise steps, you will learn the basics of blockchain technology. No mathematical formulas, program code, or computer science jargon are used. No previous knowledge in computer science, mathema......一起来看看 《Blockchain Basics》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具