Un collègue est resté bloqué à cause du problème de bug
signalé par ceci, vue2 est ce problème de pointage
, et la fonction flèche a été utilisée, ce qui a entraîné l'échec de l'obtention du accessoires
>. Il ne le savait pas quand je le lui ai présenté, puis j'ai délibérément regardé le groupe de communication front-end. Jusqu'à présent, au moins 70 % des programmeurs front-end ne peuvent pas le comprendre. Aujourd'hui, je vais partager avec vous. ce code>Montrez-le, si vous n'avez rien appris, s'il vous plaît, faites-moi une grande gueule. <code>bug
,vue2的this指向问题
,使用了箭头函数,导致拿不到对应的props
。当我给他介绍的时候他竟然不知道,随后也刻意的看了一下前端交流群,至今最起码还有70%以上的前端程序员搞不明白,今天给大家分享一下this
指向,如果啥都没学会,请给我一个大嘴巴子。
this
指向跟在哪里定义无关,跟如何调用,通过什么样的形式调用有关this
(这个) 这个函数如何被调用(方便记忆) 上面我们介绍了,this
的指向主要跟通过什么样的形式调用有关。接下来我就给大家介绍一下调用规则,没有规矩不成方圆,大家把这几种调用规则牢记于心就行了,没有什么难的地方。
函数最常用的调用方式,调用函数的类型:独立函数调用
function bar() { console.log(this) // window }
window
this
为undefined
用最通俗的话表示就是:对象拥有某个方法,通过这个对象访问方法且直接调用(注:箭头函数特殊,下面会讲解)
const info = { fullName: 'ice', getName: function() { console.log(this.fullName) } } info.getName() // 'ice'
info
发起调用,进行了隐式绑定,所以当前的this
为info
,通过this.fullName
毫无疑问的就访问值为ice
隐式丢失 普通
有些情况下会进行隐式丢失,被隐式绑定的函数会丢失绑定对象,也就是说它为变为默认绑定,默认绑定的this
值,为window
还是undefined
取决于您当前所处的环境,是否为严格模式。
const info = { fullName: 'ice', getName: function() { console.log(this.fullName) } } const fn = info.getName fn() //undefined
这种情况下就进行了隐式丢失,丢失了绑定的对象,为什么会产生这样的问题呢?如果熟悉内存的小伙伴,就会很容易理解。
info
找到了对应getName
的内存地址,赋值给变量fn
fn
直接进行了调用window
,从window
中取出fullName
属性,必定为undefined
隐式丢失 进阶
这里大家首先要理解什么是回调函数。其实可以这样理解,就是我现在不调用它,把他通过参数的形式传入到其他地方,在别的地方调用它。
//申明变量关键字必须为var var fullName = 'panpan' const info = { fullName: 'ice', getName: function() { console.log(this.fullName) } } function bar(fn) { //fn = info.getName fn() // panpan } bar(info.getName)
bar
中的fn
为一个回调函数fn = info.getName
参数传递就是一种隐式赋值,其实跟上面的隐式丢失是一个意思,他们都是指向的fn = info.getName
引用,也就是它们的内存地址this
丢失,也就是函数独立调用,默认绑定规则,this
为全局的window
对象var
呢?var
申明的变量才会加入到全局window
对象上letconst
则不是,具体的后续介绍一下这两个申明变量的关键字 但是在某些场景下,this
的改变都是意想不到的,实际上我们无法控制回调函数的执行方式,因此没有办法控制调用位置已得到期望的绑定即this指向。
接下来的显示绑定就可以用来解决这一隐式丢失问题。
js中的 ”所有“函数都有一些有用的特性,这个跟它的原型链有关系,后续我会在原型介绍,通过原型链js中变相实现继承的方法,其中call/apply/bind
this
pointe vers une fonction qui n'a rien à voir avec l'endroit où elle est définie, mais comment elle est appelée et sous quelle formethis(this) Comment être appelé (facile à retenir)
this
est principalement lié à la forme d'appel. Ensuite, je vais vous présenter les règles d'appel. Sans règles, rien n'est complet. Gardez simplement ces règles d'appel à l'esprit. Il n'y a rien de difficile. 🎜var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) } } function bar(fn) { fn.call(info, 20, 1.88) //ice 20 1.88 } bar(info.getName)
window
ce
ici est non défini
var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) } } function bar(fn) { fn.apply(info, [20, 1.88]) //ice 20 1.88 } bar(info.getName)
info
et implicitement liée, donc le this
actuel est info, via this.fullName
il ne fait aucun doute que la valeur d'accès est ice
this
de la liaison par défaut, qu'il s'agisse de window code> ou <code>undefined
dépend de l'environnement dans lequel vous vous trouvez actuellement, s'il s'agit d'un mode strict. 🎜var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) //ice 20 1.88 } } function bar(fn) { let newFn = fn.bind(info, 20) newFn(1.88) } bar(info.getName)
getName
est trouvée via info
et affectée à la variable fn code>
fn
window, from fullName
extrait de code>windowundefined
🎜Perte implicite Avancé function Person(name, age) { this.name = name this.age = age } const p1 = new Person('ice', 20) console.log(p1) // {name:'ice', age:20}
fn
dans bar
est une fonction de rappelfn = info.getName code> Le passage de paramètres est une sorte d'affectation implicite. En fait, cela a la même signification que la perte implicite ci-dessus. Ils pointent tous vers des références <code>fn = info.getName
, qui sont leurs adresses mémoireli>Parce que leur this
est perdu, c'est-à-dire que la fonction est appelée indépendamment et la règle de liaison par défaut est que this
est la fenêtre
globale. code> objetvar
? var
seront ajoutées à l'objet global window
letconst
est utilisé > Non, je présenterai les deux mots-clés pour déclarer les variables en détail plus tard this
Le les changements sont inattendus. En fait, nous n'avons aucun contrôle sur la façon dont la fonction de rappel est exécutée, il n'y a donc aucun moyen de contrôler que l'emplacement appelant a obtenu la liaison attendue, c'est-à-dire qu'il y pointe. 🎜🎜La prochaine liaison d'affichage peut être utilisée pour résoudre ce problème de perte implicite. 🎜call()
方法使用一个指定的 this
值和单独给出的一个或多个参数来调用一个函数。this
对象apply()
方法类似,只有一个区别,就是 call()
方法接受的是一个参数列表,而 apply()
方法接受的是一个包含多个参数的数组。var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) } } function bar(fn) { fn.call(info, 20, 1.88) //ice 20 1.88 } bar(info.getName)
call
的方法类似,只是参数列表有所不同call
参数为单个传递apply
参数为数组传递var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) } } function bar(fn) { fn.apply(info, [20, 1.88]) //ice 20 1.88 } bar(info.getName)
bind
与apply/call
之间有所不同,bind
传入this
,则是返回一个this
绑定后的函数,调用返回后的函数,就可以拿到期望的this。bind
时,可以传入参数bind
返回的参数也可以进行传参var fullName = 'panpan' const info = { fullName: 'ice', getName: function(age, height) { console.log(this.fullName, age, height) //ice 20 1.88 } } function bar(fn) { let newFn = fn.bind(info, 20) newFn(1.88) } bar(info.getName)
谈到new
关键字,就不得不谈构造函数,也就是JS中的 "类",后续原型篇章在跟大家继续探讨这个new关键字,首先要明白以下几点,new Fn()
的时候发生了什么,有利于我们理解this
的指向。
创建了一个空对象
将this指向所创建出来的对象
把这个对象的[[prototype]] 指向了构造函数的prototype属性
执行代码块代码
如果没有明确返回一个非空对象,那么返回的对象就是这个创建出来的对象
function Person(name, age) { this.name = name this.age = age } const p1 = new Person('ice', 20) console.log(p1) // {name:'ice', age:20}
new Person()
的时候,那个this所指向的其实就是p1
对象function bar() { console.log(this) //info } const info = { bar: bar } info.bar()
widonw或者undefined
,变相的可以认为隐式绑定 > 默认绑定var fullName = 'global ice' const info = { fullName: 'ice', getName: function() { console.log(this.fullName) } } info.getName.call(this) //global ice info.getName.apply(this) //global ice info.getName.bind(this)() //global ice
function bar() { console.log(this) //123 } const newFn = bar.bind(123) newFn.call(456)
首先我们来说一下,为什么是和bind
比较,而不能对call
和apply
比较,思考下面代码
const info = { height: 1.88 } function Person(name, age) { this.name = name this.age = age } const p1 = new Person.call('ice', 20) //报错: Uncaught TypeError: Person.call is not a constructor
new绑定和bind绑定比较
const info = { height: 1.88 } function Person(name, age) { this.name = name this.age = age } const hasBindPerson = Person.bind(info) const p1 = new hasBindPerson('ice', 20) console.log(info) //{height: 1.88}
bind
对Person
进行了一次劫持,硬绑定了this为info
对象new
返回的固定this的函数new关键字
> bind
> apply/call
> 隐式绑定
> 默认绑定
首先箭头函数是ES6
新增的语法
const foo = () => {}
var fullName = 'global ice' const info = { fullName: 'ice', getName: () => { console.log(this.fullName) } } info.getName() //global ice
ice
ES6
的新特性,箭头函数不绑定this
,它的this
是上一层作用域,上一层作用域为window
global ice
getObjName
通过this
拿到info
中的fullName
(值为ice
的fullName
)const info = { fullName: 'ice', getName: function() { let _this = this return { fullName: 'panpan', getObjName: function() { console.log(this) // obj console.log(_this.fullName) } } } } const obj = info.getName() obj.getObjName()
当我调用 info.getName()
返回了一个新对象
当我调用返回对象的getObjName
方法时,我想拿到最外层的fullName
,我通过,getObjName
的this访问,拿到的this却是obj
,不是我想要的结果
我需要在调用info.getName()
把this保存下来,info.getName()
是通过隐式调用,所以它内部的this就是info对象
getObjName
是obj对象,因为也是隐式绑定,this必定是obj对象,绕了一大圈我只是想拿到上层作用域的this而已,恰好箭头函数解决了这一问题
const info = { fullName: 'ice', getName: function() { return { fullName: 'panpan', getObjName: () => { console.log(this.fullName) } } } } const obj = info.getName() obj.getObjName()
默认绑定
隐式绑定
显示绑定 apply/call/bind(也称硬绑定)
new绑定
new绑定
bind
call/apply
隐式绑定
默认绑定
当一切都看起来不起作用的时候,我就会像个石匠一样去敲打石头,可能敲100次,石头没有任何反应,但是101次,石头可能就会裂为两半 我知道并不是第101次起了作用,而是前面积累所致。
大家有疑惑可以在评论区留言 第一时间为大家解答。
(学习视频分享:web前端开发)