首页 > web前端 > js教程 > 正文

Javascript中什么是this?this的4种绑定方式(介绍)

青灯夜游
发布: 2018-09-21 17:19:22
原创
2786人浏览过

本章给大家带来javascript中什么是this?this的4种绑定方式(介绍)。有一定的参考价值,有需要的朋友可以参考一下,希望对你们有所帮助。

什么是this?

当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。

this的4种绑定方式

默认绑定

function foo() { 
    console.log( this.a );
}
var a = 2;
foo(); // 2
登录后复制

这段代码输出2 , 说明this默认绑定到了全局对象

立即学习Java免费学习笔记(深入)”;

隐式绑定

function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};
obj.foo(); // 2
登录后复制

这段代码this绑定到了obj对象,当函数引用有上下文对象(context)时,隐式绑定规则会把this绑定到这个上下文对象。

隐式丢失问题

// 例子1111
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};
var bar = obj.foo; // 函数别名!

var a = "oops, global"; // a是全局对象的属性”

bar();  // "oops, global"
//2222
function foo() { 
    console.log( this.a );
}
var obj = { 
    a: 2,
    foo: foo 
};

var a = "oops, global"; // a是全局对象的属性

setTimeout( obj.foo, 100 ); // "oops, global
登录后复制

例子1111虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此应用了默认绑定。例子222在setTimeout函数中丢失了this绑定,道理是一样的,我们可以把参数传递看成一种隐式赋值。

显式绑定

在分析隐式绑定时,我们必须在一个对象内部包含一个指向函数的属性,并通过这个属性间接引用函数,从而把this间接(隐式)绑定到这个对象上。

那么如果我们不想在对象内部包含函数引用,而想在某个对象上强制调用函数,该怎么做呢?

学过js的估计对 call,apply和bind都不陌生,js提供的这些原生方法就给我们提供了显式绑定this的途径。

function foo() { 
    console.log( this.a );
}var obj = { 
    a:2};

foo.call( obj ); // 2
登录后复制

通过foo.call(..),我们可以在调用foo时强制把它的this绑定到obj上。

如果你传入了一个原始值(字符串类型、布尔类型或者数字类型)来当作this的绑定对象,这个原始值会被转换成它的对象形式(也就是new String(..)、new Boolean(..)或者new Number(..))。这通常被称为“装箱”。

“从this绑定的角度来说,call(..)和apply(..)是一样的,它们的区别体现在其他的参数上,但是现在我们不用考虑这些。”

硬绑定-bind的实现

Find JSON Path Online
Find JSON Path Online

Easily find JSON paths within JSON objects using our intuitive Json Path Finder

Find JSON Path Online 193
查看详情 Find JSON Path Online

我们已经知道了this绑定的4种方式,但是使用call和apply我们还是不能解决隐式丢失的问题,思考以下例子:

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

var obj = { 
    a:2
};

var bar = function() {
    foo.call( obj );
};

bar(); // 2
setTimeout( bar, 100 ); // 2

bar.call(windows) //无法再修改this
登录后复制

通过call我们在函数bar内强制指定了foo的this,之后不论如何调用bar,它总会在obj上手动调用foo,这种绑定是一种显示强制绑定,因此称为硬绑定。这就是bind的产生来由(因为硬绑定比较常用,es5中新增了bind方法),通过硬绑定制定this,上面代码现在就变成了

...略var bar = foo.bind(obj)
bar(); // 2setTimeout( bar, 100 ); // 2
登录后复制

绑定规则优先级和es6的this新特性

如果要判断一个运行中函数的this绑定,就需要找到这个函数的直接调用位置。找到之后就可以顺序应用下面这四条规则来判断this的绑定对象。

  1. 由new调用?绑定到新创建的对象。

  2. 由call或者apply(或者bind)调用?绑定到指定的对象。

  3. 由上下文对象调用?绑定到那个上下文对象。

  4. 默认:在严格模式下绑定到undefined,否则绑定到全局对象。

几个小例子看懂this

unction showThis () {  console.log(this)
}function showStrictThis () {  'use strict'
  console.log(this)
}
showThis() // windowshowStrictThis() // undefined
登录后复制

优先级最小的this对象,默认绑定。

思考下面的例子:

var person = {  name: '11',
  showThis () {    return this
  }
}

person.showThis() === person  //truevar person2 = { name: '22',
  showThis () {    return person.showThis()
  }
}var person3 = { name: '33',
  showThis () {    var retrunThis = person.showThis    return retrunThis()
  }
}

person.showThis()  //personperson2.showThis()  //?person3.showThis()  //?
登录后复制

我们首先要找到调用位置,在2里是这句return person.showThis(),隐式绑定了一个person对象,所以输出person ,3 是return retrunThis() ,this默认绑定到全局,返回window.

function showThis () {  
return this
}
var person = { name: 'person' }
showThis() // window
showThis.call(p1) // person
showThis.apply(p1) // person
登录后复制

通过显式绑定指定了context object。

function showThis () {
  return this
}
var person = { name: 'person' }

var personBind = showThis.bind(person)

personBind()   //person

var person2 = { name: 'person2' }

personBind.call(person2) //person
登录后复制

bind方法强绑定了this,已经无法再通过显式绑定切换this。

function showThis () {
  return this
}
var person = { name: 'person' }
var person2 = { name: 'person2' }

var personBind = showThis.bind(person)

personBind()    //person
new personBind()  //showThis
登录后复制

new优先级高于bind,所以可以覆盖this。

function foo() { 
    setTimeout(() => {        
        // 这里的this在词法上继承自foo()
        console.log( this.a ); 
    },100);
}var obj = { 
    a:2};

foo.call( obj ); // 2
登录后复制

箭头函数并不是使用function关键字定义的,而是使用被称为“胖箭头”的操作符=>定义的。箭头函数不使用this的四种标准规则,而是根据外层(函数或者全局)作用域来决定this。箭头函数的绑定无法被修改,包括new。 关于箭头函数网上有很多详细全面的讲解。这里不再展开。

以上就是Javascript中什么是this?this的4种绑定方式(介绍)的详细内容,更多请关注php中文网其它相关文章!

相关标签:
java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号