我是JavaScript的新手。我所做的全部内容都是对现有代码的调整,并编写了一小部分jQuery。
现在我正在尝试用属性和方法编写一个“类”,但是我遇到了这些方法的问题。我的代码:
function Request(destination, stay_open) {
this.state = "ready";
this.xhr = null;
this.destination = destination;
this.stay_open = stay_open;
this.open = function(data) {
this.xhr = $.ajax({
url: destination,
success: this.handle_response,
error: this.handle_failure,
timeout: 100000000,
data: data,
dataType: 'json',
});
};
/* snip... */
}
Request.prototype.start = function() {
if( this.stay_open == true ) {
this.open({msg: 'listen'});
} else {
}
};
//all console.log's omitted
问题是,在Request.prototype.start
中,this
未定义,因此if语句的计算结果为false。我在这做错了什么?
答案 0 :(得分:53)
你是如何调用启动功能的?
这应该有效(新是关键)
var o = new Request(destination, stay_open);
o.start();
如果您直接将其称为Request.prototype.start()
,this
将引用全局上下文(浏览器中为window
)。
此外,如果未定义this
,则会导致错误。 if表达式的计算结果为false。
更新:this
对象未根据声明设置,而是通过调用设置。这意味着如果您将函数属性分配给x = o.start
之类的变量并调用x()
,则{start}内的this
不再引用o
。执行setTimeout
时会发生这种情况。为了使其有效,请改为:
var o = new Request(...);
setTimeout(function() { o.start(); }, 1000);
答案 1 :(得分:15)
JavaScript的OOP有点时髦(或很多),需要一些时间来适应。首先要记住的是没有类并且根据类来思考可能会让你失望。并且为了使用附加到构造函数的方法(类似于类定义的JavaScript),您需要实例化对象。例如:
Ninja = function (name) {
this.name = name;
};
aNinja = new Ninja('foxy');
aNinja.name; //-> 'foxy'
enemyNinja = new Ninja('boggis');
enemyNinja.name; //=> 'boggis'
请注意,Ninja
个实例具有相同的属性,但aNinja
无法访问enemyNinja
的属性。 (这部分应该非常简单/直接)当您开始向prototype
添加内容时,情况会有所不同:
Ninja.prototype.jump = function () {
return this.name + ' jumped!';
};
Ninja.prototype.jump(); //-> Error.
aNinja.jump(); //-> 'foxy jumped!'
enemyNinja.jump(); //-> 'boggis jumped!'
直接调用此方法会引发错误,因为this
仅在实例化构造函数时指向正确的对象(您的“类”)(否则它指向浏览器中的全局对象window
)
答案 2 :(得分:4)
在ES2015 a.k.a ES6中,class
是functions
的语法糖。
如果您想强制为this
设置上下文,可以使用bind()
方法。正如@chetan指出的那样,在调用时你也可以设置上下文!请查看以下示例:
class Form extends React.Component {
constructor() {
super();
}
handleChange(e) {
switch (e.target.id) {
case 'owner':
this.setState({owner: e.target.value});
break;
default:
}
}
render() {
return (
<form onSubmit={this.handleNewCodeBlock}>
<p>Owner:</p> <input onChange={this.handleChange.bind(this)} />
</form>
);
}
}
这里我们将handleChange()
内的上下文强制转换为Form
。
答案 3 :(得分:4)
以前的答案都没有为我提供完整的解决方案,因此请在此处发布我的答案。
我有一个类,当我在方法引用上运行 forEach
时返回错误。
例如
class Foo {
hello (name) {
return `hello ${name}`
}
doGreet (name) {
return console.log(this.hello(name)) // <- 'this' is undefined
}
}
// print some names...
const foo = new Foo();
(['nick', 'john']).forEach(foo.doGreet)
// TypeError: Cannot read property 'hello' of undefined
// at doGreet (/.../test.js:7:17)
解决方案是在构造函数中绑定方法的 this
的上下文。即
class Foo {
constructor () {
this.doGreet = this.doGreet.bind(this)
}
// ... yada yada ...
}
答案 4 :(得分:3)
我只是想指出,有时会发生此错误,因为某个函数被用作高阶函数(作为参数传递),然后this
的范围丢失了。在这种情况下,我建议传递绑定到this
的函数。例如
this.myFunction.bind(this);
答案 5 :(得分:0)
这个问题已经回答,但是也许有人可能会来这里。
当我愚蠢地尝试在初始化类的方法时破坏其结构时,我还遇到了this
未定义的问题:
import MyClass from "./myClass"
// 'this' is not defined here:
const { aMethod } = new MyClass()
aMethod() // error: 'this' is not defined
// So instead, init as you would normally:
const myClass = new MyClass()
myClass.aMethod() // OK
答案 6 :(得分:0)
使用箭头功能:
Request.prototype.start = () => {
if( this.stay_open == true ) {
this.open({msg: 'listen'});
} else {
}
};