gpt4 book ai didi

javascript - 与 es6 类和 jquery 绑定(bind)

转载 作者:行者123 更新时间:2023-11-29 10:33:17 27 4
gpt4 key购买 nike

在做一个项目时,我注意到当通过 jquery 调用访问时,类方法中的 this 并没有真正附加到实例,甚至也没有附加到类。相反,我看到的是 window 全局,这是不对的。

所以有多种方法可以为您自动绑定(bind)它。我尝试了几个,但没有成功。这是怎么回事?

这里是错误:

Uncaught TypeError: this.chooseAtRandom is not a function
at move (pen.js:83)
move @ pen.js:83
pen.js:102 Uncaught TypeError: Cannot read property 'push' of undefined
at UIController.animate (pen.js:102)
at HTMLDivElement.<anonymous> (pen.js:131)
at HTMLDivElement.dispatch (jquery.min.js:3)
at HTMLDivElement.q.handle (jquery.min.js:3)
animate @ pen.js:102
(anonymous) @ pen.js:131
dispatch @ jquery.min.js:3
q.handle @ jquery.min.js:3
pen.js:83 Uncaught TypeError: this.chooseAtRandom is not a function
at move (pen.js:83)

这是我的自动绑定(bind)方法:

class Binder {
getAllMethods(instance, cls) {
return Object.getOwnPropertyNames(Object.getPrototypeOf(instance))
.filter(name => {
let method = instance[name]
return !(!(method instanceof Function) || method === cls)
})
}
bind(instance, cls) {
Binder.getAllMethods(instance, cls)
.forEach(mtd => {
instance[mtd] = instance[mtd].bind(instance);
})
}
}

请注意其中的 Binder.getAllMethods 调用。如果我将其更改为 this.getAllMethods 我也会在这里遇到问题。我想知道 codepen 是否破坏了它

这是我在使用它:

class SimonAudio {
constructor() {
this.soundsrcs = [
'https://s3.amazonaws.com/freecodecamp/simonSound1.mp3',
'https://s3.amazonaws.com/freecodecamp/simonSound2.mp3',
'https://s3.amazonaws.com/freecodecamp/simonSound3.mp3',
'https://s3.amazonaws.com/freecodecamp/simonSound4.mp3'
]
this.players = this.soundsrcs.map(s => {
let a = document.createElement('audio');
a.setAttribute('src', s)
return a
})
this.uiMap = {
red: 0,
green: 1,
amarillo: 2,
blue: 3
}

Binder.bind(this, SimonAudio)
}
play(uiId) {
this.players[this.uiMap[uiId]].play()
}
}

class Game {
constructor(UI) {
this.UI = UI
this.uiMap = {
red: 0,
green: 1,
amarillo: 2,
blue: 3
};
this.dexUi = ['red', 'green', 'amarillo', 'blue']
this.states = ['SHOWINGCHALLENGE', 'LISTENING']
this.audio = new SimonAudio()
this.moves = []
this.gameStack = []
this.inGame = false

Binder.bind(this, Game)
}

start() {
this.inGame = true
this.gameStack.push(setTimeout(this.move, parseInt((Math.random() + 1) * 1000)))
}
restart() {
this.moves = []
this.gameStack.forEach(a => {
clearTimeout(a)
})
this.gameStack = []
this.inGame = false
}
playMoves() {
let elf = this.UI
this.moves.forEach(m =>
this.gameStack.push(
setTimeout(function() {
elf.animate(m)
}, parseInt((Math.random() + 1) * 500)))
)
}
move() {
let move = this.chooseAtRandom()
this.moves.push(move)
this.playMoves()
}
chooseAtRandom() {
return this.dexUi[parseInt(Math.random() * 4)]
}
}

class UIController {
contructor() {
this.animation_stack = []
Binder.bind(this, UIController)
}
clear() {
this.animation_stack.forEach(a => clearTimeout(a))
this.animation_stack = []
}
animate(uiId) {
$(`#${uiId}`).addClass('highlight')
this.animation_stack.push(setTimeout(function() {
$(`#${uiId}`).removeClass('highlight')
}, 333))
}
}

然后是炸毁它的 jquery:

$(function() {
let UI = new UIController()
let Simon = new Game(UI)

$('#strict').click(function() {
$(this).toggleClass('toggled')
})

$('#restart').click(function() {
$('.controls .button').removeClass('disabled toggled')
$('.game-buttons div').addClass('disabled')
Simon.restart()
})

$('#start').click(function() {
if (Game.inGame)
return
$('.game-buttons > div').addClass('hvr-radial-out')
$(this).addClass('toggled')
$('#strict').addClass('disabled')
$('.game-buttons div').removeClass('disabled')
Simon.start()
})

$('.game-buttons div').addClass('disabled')
.click(function() {
if ($(this).hasClass('disabled'))
return
let id = $(this).attr('id')
UI.animate(id)
Simon.audio.play(id)
})

})

最佳答案

Uncaught TypeError: this.chooseAtRandom is not a function

好吧,让我们看看调用代码

move() {
let move = <b>this.chooseAtRandom()</b>
this.moves.push(move)
this.playMoves()
}

OK,现在让我们看一下move的调用代码

start() {  this.inGame = true  this.gameStack.push(setTimeout(this.move, parseInt((Math.random() + 1) * 1000)))}

OK, right there you lose the this context you hope to preserve when the function actually fires. We can easily rewrite this in a couple of ways. But before I start copying/pasting another really bad part of your code, I have to fix that first.

// parseInt is for converting strings to numbers
// Math.random() gives you a number so you don't need to parse it
// change this
parseInt((Math.random() + 1) * 1000)

// to this
(Math.random() + 1) * 1000

好的,现在让我们修复你的函数上下文

// Option 1: use Function.prototype.bind
this.gameStack.push(setTimeout(this.move.bind(this), (Math.random() + 1) * 1000))

// Option 2: use a sexy ES6 arrow function
this.gameStack.push(setTimeout(() => this.move(), (Math.random() + 1) * 1000))

好的,现在让我们检查 start 是否在正确的上下文中调用

$('#start').click(function() {
if (Game.inGame)
return
$('.game-buttons > div').addClass('hvr-radial-out')
$(this).addClass('toggled')
$('#strict').addClass('disabled')
$('.game-buttons div').removeClass('disabled')
<b>Simon.start()</b>
})

好的! start 函数中的 this 将设置为 GameSimon 实例。我无法运行您的其余代码,所以我不知道是否还有其他问题,但这应该可以解决您之前看到的 this.chooseAtRandom is not a function 错误。

好的。

关于javascript - 与 es6 类和 jquery 绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41253813/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com