我有一个构造函数,它注册一个事件处理程序:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', function () {
alert(this.data);
});
}
// Mock transport object
var transport = {
on: function(event, callback) {
setTimeout(callback, 1000);
}
};
// called as
var obj = new MyConstructor('foo', transport);Run Code Online (Sandbox Code Playgroud)
但是,我无法data在回调中访问已创建对象的属性.它看起来this并不是指创建的对象,而是指另一个对象.
我还尝试使用对象方法而不是匿名函数:
function MyConstructor(data, transport) {
this.data = data;
transport.on('data', this.alert);
}
MyConstructor.prototype.alert = function() {
alert(this.name);
};
Run Code Online (Sandbox Code Playgroud)
但它表现出同样的问题.
如何访问正确的对象?
this在对象原型中存储的事件处理程序中保留javascript引用的正确方法是什么?我想远离创建像'_this'或'that'这样的临时变量,我不能使用像jQuery这样的框架.我看到很多人谈论使用'绑定'功能但不确定如何在我给定的场景中实现它.
var Example = function(foo,bar){
this.foo = foo;
this.bar = bar;
};
Example.prototype.SetEvent = function(){
this.bar.onclick = this.ClickEvent;
};
Example.prototype.ClickEvent = function(){
console.log(this.foo); // logs undefined because 'this' is really 'this.bar'
};
Run Code Online (Sandbox Code Playgroud) 请原谅我的无知,因为我对jquery并不熟悉.是否有相当于dojo.hitch()的东西?它返回一个保证在给定范围内执行的函数.
- 编辑 - 根据要求,这是一个例子.我经常使用hitch来确保在正确的对象中执行回调.例如,假设我调用了一个实用程序方法doSomethingAsync,并将其传递给回调函数.有了故障,我可以确保函数在特定范围内执行,即使实用程序方法执行ajax调用等等:
expectedScopeObj = {
flag: true,
callback: function(){console.debug(this.flag);},
main: function() {
// without hitch the callback function would not find flag
core.util.doSomethingAsync(dojo.hitch(this, this.callback));
}
}
Run Code Online (Sandbox Code Playgroud)
没有故障,回调函数可能在不同的范围内执行,并且this.flag在未定义的情况下会抛出错误.然而,有了障碍,它保证在内部执行execptedScopeObj.
我正在研究一个项目一段时间,试图找出我做错了什么,当我最终将"错误"缩小到下面的代码不能按预期工作的事实时:
function Alpha()
{
this.onion = 'onion';
function Beta()
{
alert(this.onion);
}
Beta();
}
alpha1 = new Alpha();
// Alerts 'undefined'
Run Code Online (Sandbox Code Playgroud)
但是,如果我将代码更改为:
function Alpha()
{
var self = this;
this.onion = 'onion';
function Beta()
{
alert(self.onion);
}
Beta();
}
alpha1 = new Alpha();
// Alerts 'onion'
Run Code Online (Sandbox Code Playgroud)
它像我期望的那样工作.在浪费了我生命中的大部分时间之后,任何人都可以解释为什么它会像这样工作吗?
为什么不能eval在with语句下使用范围变量?
例如:
(function (obj) {
with (obj) {
console.log(a); // prints out obj.a
eval("console.log(a)"); // ReferenceError: a is not defined
}
})({ a: "hello" })
Run Code Online (Sandbox Code Playgroud)
编辑:正如知识渊博的CMS所指出的,这似乎是一个浏览器错误(使用WebKit控制台的浏览器).
如果有人想知道我试图提出什么憎恶,那将需要"邪恶" eval和with- 我试图看看我是否可以获得一个函数(用作回调)在另一个上下文中执行而不是它被定义为.不,我可能(咳)不会在任何地方使用它...比任何事都更好奇.
(function (context,fn) {
with (context)
eval("("+fn+")()");
})({ a: "hello there" }, function () { console.log(a); })
Run Code Online (Sandbox Code Playgroud) 我有类似的东西:
var a = (function () {
return {
b: 1,
c: function () {
console.log(this.b);
}
};
})();
Run Code Online (Sandbox Code Playgroud)
所以,
a.c(); // = 1
Run Code Online (Sandbox Code Playgroud)
但如果我这样做
b = 2;
a.c.apply(this); // = 2
Run Code Online (Sandbox Code Playgroud)
是否有可能在"ac()"中保留"this"的上下文而不改变(太多)"a"对象的结构?我没有对函数调用的控制,所以我需要一个解决方法来处理对象本身内部的这个问题.
更新:
更具体地说,这是我的文件的结构:
结构1(单身模式):
var a = (function () {
var _instance;
function init() {
return {
b: 1,
c: function () {
console.log(this.b);
}
};
}
return {
getInstance: function () {
if (_instance === undefined) {
_instance = init();
}
return _instance;
}
}
})(); …Run Code Online (Sandbox Code Playgroud) 我刚刚开始尝试类和异步等待。我使用的是 Node 版本 8.9.0 (LTS)。当 I 时console.log(this),我得到undefined而不是对对象的引用。
子处理程序.js
class Handler {
constructor(props) {
this.defaultRes = {
data: successMessage,
statusCode: 200
};
}
async respond(handler, reply, response = this.defaultRes) {
console.log(this); // why is `this` undefined????
try {
await handler;
return reply(response.data).code(response.statusCode)
} catch(error) {
return reply(error);
}
}
}
class SubHandler extends Handler {
constructor(props) {
super(props);
this.something = 'else';
}
makeRequest(request, reply) {
console.log(this); // why is `this` undefined!!
// in this case, doSomeAsyncRequest is …Run Code Online (Sandbox Code Playgroud) 我正试图逐渐增加反击.以下作品:
function _award(points){
var step = 1;
while(points){
var diff = Math.ceil(points / 10);
setTimeout( "_change_score_by("+diff+");" /* sigh */,
step * 25);
points -= diff;
step++;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,它使用隐式eval.邪恶!让我们使用一个闭包,对吧?
function _award(points){
var step = 1;
while(points){
var diff = Math.ceil(points / 10);
setTimeout( function(){ _change_score_by(diff); },
step * 25);
points -= diff;
step++;
}
}
Run Code Online (Sandbox Code Playgroud)
显然,这不起作用.创建的所有闭包捕获diff函数中的最后一个值- 1.因此,所有匿名函数都会将计数器增加1,例如,_award(100)将得分增加28.
我该怎么做呢?
运行以下代码:
for (var i=0; i<3; i++) {
setTimeout( function() { console.log(i); } , 500 );
}
Run Code Online (Sandbox Code Playgroud)
输出"3"三次.它输出的是最终值,i而不是i创建内部函数时的值.
如果我想输出为1,2和3,我该如何编写这段代码?如何使用i函数定义时的值而不是最终值?
'this' 关键字在全局对象中使用时指的是什么?
假设我们有:
var SomeGlobalObject =
{
rendered: true,
show: function()
{
/*
I should use 'SomeGlobalObject.rendered' below, otherwise it
won't work when called from event scope.
But it works when called from timer scope!!
How can this be?
*/
if(this.rendered)
alert("hello");
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我们在 HTML 页面中调用内联脚本:
SomeGlobalObject.show();
window.setTimeout("SomeGlobalObject.show()", 1000);
Run Code Online (Sandbox Code Playgroud)
一切正常。
但是如果我们做这样的事情:
AppendEvent(window, 'load', SomeGlobalObject.show);
Run Code Online (Sandbox Code Playgroud)
我们收到错误,因为this.rendered从事件范围调用时未定义。
AppendEvent 只是一个简单的跨浏览器函数来追加一个事件,代码如下,但是为了回答上面的问题没有关系。
function AppendEvent(html_element, event_name, event_function)
{
if(html_element.attachEvent) //IE
return html_element.attachEvent("on" + event_name, event_function);
else
if(html_element.addEventListener) //FF
html_element.addEventListener(event_name, …Run Code Online (Sandbox Code Playgroud) 我试图设计一些类来支持回调功能.类MyClass1和MyClass2不起作用.Class3工作,但设计真的很糟糕.它使用外部类引用来调用方法.我想实现一个类似于MyClass1的设计,它更加清晰,不会与外部变量耦合.这个回调机制对于ajax调用来说真的很棒.$ j只是jQuery的别名.
function MyClass1() {
$j("#myDiv1").click(this.func);
this.func = function() {
alert("Inside method.");
}
}
var _class2;
function MyClass2() {
_class2 = this;
$j("#myDiv2").click( _class2.func );
this.func = function() {
alert("Inside method.");
}
}
function MyClass3() {
$j("#myDiv3").click( function() { cls3.func(); } );
this.func = function() {
alert("Inside method.");
}
}
var cls1 = new MyClass1();
var cls2 = new MyClass2();
var cls3 = new MyClass3();
Run Code Online (Sandbox Code Playgroud) 我正在尝试在Javascript中使用原型继承.下面我的代码的问题是,当单击按钮并被MyNamespace.MyObj.myEventHandler调用时,值this不是实例MyNamespace.MyObj,而是单击的按钮.
我构建错误的东西(有更好的方法)吗?我可以以某种方式确保这this是对象的实例而不是调用者按钮吗?
var MyNamespace.MyObj = function(myform) {
this.myform = myform;
jQuery('.mybutton', this.myform).click(this.myEventHandler);
};
MyNamespace.MyObj.prototype = {
myEventHandler: function() {
this.myform.get(0).submit();
}
};
jQuery(document).ready(function() {
new MyNamespace.MyObj(jQuery('#myform'));
});
Run Code Online (Sandbox Code Playgroud)
这只是我用来学习原型继承的一个非常愚蠢的例子.我意识到上面代码的实际功能可以简单地在jQuery中完成,或者我可以使用对象文字或模块模式 - 但我真的只是对学习原型继承而不是在此时实现特定函数感兴趣.
javascript ×11
this ×5
closures ×2
jquery ×2
object ×2
async-await ×1
callback ×1
dom-events ×1
ecmascript-6 ×1
eval ×1
hapijs ×1
oop ×1
private ×1
scope ×1
singleton ×1