广州凡科互联网科技有限公司

营业时间
MON-SAT 9:00-18:00

全国服务热线
18720358503

公司门店地址
广州市海珠区工业大道北67号凤凰创意园

百度微信小程序_JS中this的4种绑定规则详解

日期:2021-01-06 浏览:
JS中this的4种绑定规则详解       如果你学过面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不用看这篇文章,this既不指向函数自身,也不指函数的词法作用域,具体怎么使用JS中的this,JS中的this绑定规则又是什么?
JS中this是什么

理解this之前, 先纠正一个观点,this 既不指向函数自身,也不指函数的词法作用域。

如果仅通过this的英文解释,太容易产生误导了。

它实际是在函数被调用时才发生的绑定,也就是说this具体指向什么,取决于你是怎么调用的函数。也就是说谁调用的this,this就指向谁

JS中this说明

ES6中的箭头函数采用的是词法作用域。

为什么要使用this:使API设计得更简洁且易于复用。

this即不指向自身,也不指向函数的词法作用域。

this的指向只取决于函数的调用方式

this绑定规则

new 显示绑定 隐式绑定 默认绑定

当独立函数调用时,不管是否在调用栈中,this都指向全局对象(浏览器中为window)

严格模式下,不能将全局对象用于默认绑定。

var a = 2;
function foo(){
 console.log(this.a);
function bar(){
 var a = 5;
 foo();
bar(); // 2

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

对象属性引用链中只有最后一层在调用位置中起作用。

要求:对象内部必须包含一个指向函数的属性,该对象可通过这个属性间接引用函数。

function foo() {
 console.log( this.a );
var obj2 = {
 a: 42,
 foo: foo
var obj1 = {
 a: 2,
 obj2: obj2
obj1.obj2.foo(); // 42
function foo() {
 console.log( this.a );
var obj = {
 a: 2,
 foo: foo
var bar = obj.foo; // 这里bar将引用foo函数本身,所以不带有函数对象的上下文
var a = "oo凡科抠图, global"; // a是全局对象的属性
bar(); // "oo凡科抠图, global"

和回调函数的情况下(参数传递时的隐式赋值)

function foo() {
 console.log( this.a );
function doFoo(fn) {
 // 参数传递时,相当于fn = obj.foo,就和上个例子一样了
 fn(); // -- call-site!
var obj = {
 a: 2,
 foo: foo
var a = "oo凡科抠图, global"; // `a` also property on global object
doFoo( obj.foo ); // "oo凡科抠图, global"

采用call()和apply(),通过传入一个对象(若为基本类型,会被封装函数转为对象—装箱),将this绑定到该对象。

function foo() {
 console.log( this.a );
var obj = {
 a: 2
var bar = function() {
 foo.call( obj );
bar(); // 2
setTimeout( bar, 100 ); // 2
// 硬绑定后bar无论怎么调用,都不会影响foo函数的this绑定
bar.call( window ); // 2

硬绑定的典型应用是如下的包裹函数:

function foo(something) {
 console.log( this.a, something );
 return this.a + something;
var obj = {
 a: 2
var bar = function() {
 return foo.apply( obj, arguments ); // 将obj对象硬编码进去
var b = bar( 3 ); // 2 3
console.log( b ); // 5

即将内部函数用apply硬绑定到某个对象,无论怎么调用这个包裹函数,都不会影响内部函数的this。

bind辅助函数如下:

function foo(something) {
 console.log( this.a, something );
 return this.a + something;
// simple `bind` helper
function bind(fn, obj) {
 return function() {
 return fn.apply( obj, arguments ); // 利用参数将obj传入进去
var obj = {
 a: 2
var bar = bind( foo, obj ); // bind( foo, obj )会返回一个包裹函数
var b = bar( 3 ); // 2 3
console.log( b ); // 5

总结:上述包裹函数,想要包裹其他函数,只能一个一个重复写,硬编码的方式导致不能被重用,当某种功能需要多次重复使用时,将其抽象出来,成为函数。

new绑定

任何函数都可能被用作构造函数,当函数被new操作符“构造调用”时,会执行下面操作:

1. 创建一个新对象(若该函数不是JS内置的,则创建一个新的Object对象);

2. 将this绑定到这个对象;

3. 执行构造函数中的代码(为这个新对象添加属性);

4. 若函数没有返回其他对象,则自动返回这个新对象;若函数有return返回的是非对象,则还是自动返回这个新对象,即覆盖那个非对象。

function foo(a) {
 this.a = a;
var bar = new foo( 2 );
console.log( bar.a ); // 2

补充说明

间接引用

function foo() {
 console.log( this.a );
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3
(p.foo = o.foo)(); // 2,由于p.foo = o.foo的返回值是目标函数的引用,所以调用位置是foo(),而不是p.foo()或o.foo()

箭头函数:不使用这四个this规则,根据词法作用域来决定this。

function foo() {
 // 返回一个箭头函数
 return (a) = {
 // `this` here is lexically adopted from `foo()`
 console.log( this.a );
var obj1 = {
 a: 2
var obj2 = {
 a: 3
// foo()不是箭头函数,他的this被绑定到obj1
var bar = foo.call( obj1 ); // foo.call( obj1 )返回箭头函数,所以bar为箭头函数
bar.call( obj2 ); // 2! 箭头函数的this无法被修改,new也不行

如下为和箭头函数一样的模式:

function foo() {
 var self = this; // lexical capture of `this`
 setTimeout( function(){
 console.log( self.a );
 }, 100 );
var obj = {
 a: 2
};

更多关于JS中this对象的



新闻资讯

联系方式丨CONTACT

  • 全国热线:18720358503
  • 传真热线:18720358503
  • Q Q咨询:2639601583
  • 企业邮箱:2639601583@qq.com

首页
电话
短信
联系