在面向对象的JS中,咱们了解到在JS中,一切都是对象。由于一切都是对象,咱们开始明白咱们能够为函数设置和访问其余属性。而this提供了一种更优雅的方式隐式“传递”一个对象的引用。
关于this,咱们常见的误区:编程
function f1() { console.log(this) } f1() // window
关于这两个误区,其实在官方文档中有很明确的说明。数组
函数的调用方式决定了this的值。
那么this并非指向函数自己,也不是指向函数的做用域,而是在运行时进行绑定的,并非在编写时绑定,它的上下文也取决于函数调用时的各类条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。app
它指向什么彻底取决于函数在哪里被调用,也就是说,谁调用,谁负责函数
而bind()、apply()、call()则是能够更改this指向的方法this
(这部分并非翻译的原文,由于原文关于this讲的不是很细致,而我以为理解了this,才能了解bind()、apply()、call()有什么用处。因此这块是我根据《你不知道的JavaScript 上卷》this的部分,粗略的介绍了部分,有兴趣的话能够看看那本书,关于this讲的很细致。)spa
到目前为止,咱们已将函数视为由名称(可选,也能够是匿名函数)组成的对象及其在调用时执行的代码。但这不是所有真相,实际上函数看起来更接近下面的图像:翻译
如今,我将经过示例介绍每一个函数中出现的这3种相似方法。3d
官方文档说: bind()方法建立一个新函数,当调用时,将其关键字设置为提供的值。code
这很是强大。它让咱们在调用函数时明肯定义它的值。咱们来看看cooooode:对象
var pokemon = { firstname: 'Pika', lastname: 'Chu ', getPokeName: function() { var fullname = this.firstname + ' ' + this.lastname; return fullname; } }; var pokemonName = function() { console.log(this.getPokeName() + 'I choose you!'); }; var logPokemon = pokemonName.bind(pokemon); // creates new object and binds pokemon. 'this' of pokemon === pokemon now logPokemon(); // 'Pika Chu I choose you!'
让咱们分解吧。当咱们使用bind()方法时:
很酷的是,在咱们bind()一个值后,咱们能够像使用任何其余正常函数同样使用该函数。咱们甚至能够更新函数来接受参数,并像这样传递它们:
var pokemon = { firstname: 'Pika', lastname: 'Chu ', getPokeName: function() { var fullname = this.firstname + ' ' + this.lastname; return fullname; } }; var pokemonName = function(snack, hobby) { console.log(this.getPokeName() + 'I choose you!'); console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby); }; var logPokemon = pokemonName.bind(pokemon); // creates new object and binds pokemon. 'this' of pokemon === pokemon now logPokemon('sushi', 'algorithms'); // Pika Chu loves sushi and algorithms
call()的官方文档说: call()方法调用具备给定此值的函数和单独提供的参数。
这意味着,咱们能够调用任何函数,并在调用函数中明确指定what_ this _should reference_。真的相似于bind()方法!这绝对可让咱们免于编写hacky代码。
bind()和call()之间的主要区别在于call()方法:
call()和apply()用于彻底相同的目的。它们之间的惟一区别是_ call()指望全部参数都单独传递,而apply()须要一个数组。例:
var pokemon = { firstname: 'Pika', lastname: 'Chu ', getPokeName: function() { var fullname = this.firstname + ' ' + this.lastname; return fullname; } }; var pokemonName = function(snack, hobby) { console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby); }; pokemonName.call(pokemon,'sushi', 'algorithms'); // Pika Chu loves sushi and algorithms pokemonName.apply(pokemon,['sushi', 'algorithms']); // Pika Chu loves sushi and algorithms
这些内置的方法存在于每一个JS函数中都很是有用。即便你最终没有在平常编程中使用它们,你仍然会在阅读其余人的代码时常常遇到它们。