JavaScript变量作用域

JavaScript variable scopes

本文关键字:作用域 变量 JavaScript      更新时间:2023-09-26

我试图构建一个简单的应用程序,我将创建一个Box对象的多个实例,它将控制和操纵自己的数据。然而,我有麻烦弄清楚如何创建全局变量用于每个单独的对象和它的相关原型…

例如,我试图引用自身…

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );
    // I need to access this later...
    var boxName = boxData.name;
    var canvas = $( '#rm-' + boxData.id ).find( 'canvas' )[0];
    $( canvas ).on( 'mousedown', this.onMouseDownHandler );
}
Box.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( this.boxName );
}

请记住,它不能作为一个单例,因为我在任何一个时间点都会有它的多个实例。

编辑:

我在构造函数中添加了事件监听器,更新了上面的代码。

对于使用Box实例作为上下文的画布工作,您需要绑定它。

你可以尝试这样做:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );
    // I need to access this later...
    var boxName = boxData.name;
    // public property boxName
    this.boxName = boxName;
    var $canvas = $( '#rm-' + boxData.id ).find( 'canvas' );
    $canvas.on( 'mousedown', this.onMouseDownHandler.bind(this) );
    // ----------------------------------------------^
    // this bind will prevent the event use canvas element as context
}
function Room() {
    // some stuff
}
Room.prototype = new Box({name: 'this will always be my rooms box'});
Room.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( this.boxName );
}

现在你可以试一下:

var foo = new Room();
foo.onMouseClickHandler();

您的控制台将记录this will always be my rooms box

你要记住Room扩展了Box的一个实例,所以如果你这样做:

foo.boxName = 'my name is what?!';
// you changed the this so the prototype will get the new value:
foo.onMouseClickHandler(); // 'my name is what?!'

EDIT(问题升级后)

this.boxName代替var boxName:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );
    // public property boxName
    this.boxName = boxName;
}

如果你想为其他对象添加一个EventHandler,但要保留Box的上下文你需要这样做:

var foo = newBox({boxName: 'foo'});
var bar = document.queryElementById('bar');
bar.addEventHandler('click', foo.onMouseClickHandler.bind(foo));

现在,如果您单击bar元素,来自foo的onmousecickhandler将保持其上下文。click事件将被传递并抛出参数。

创建全局变量作为全局对象(窗口)的属性。您可以使用类似:window['box_instance_key']['name']的东西来存储每个实例的名称。

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );
    // I need to access this later...
    window.boxName = boxData.name;
    // or something like window[boxData.id]['boxName'] = boxData.name;
}
Room.prototype.onMouseClickHandler = function( event ) {
    // 'boxName' is undefined as 'this' references 'event.target'
    console.log( window.boxName );
}

你实际上有两个问题。

变量作用域

JS中的变量总是有函数作用域。构造函数中的局部变量将保持在构造函数的局部,不能在外部使用。

创建全局变量,以便在每个单独的对象中使用

它不能作为单例

全局静态变量似乎与您想要的相反。我猜你是指公共对象属性而不是全局变量。所以用一个:

function Box( boxData ) {
    // References the Box instance as I want.
    console.log( this );
    // create a property to be accessed later...
    this.boxName = boxData.name;
}

'boxName'未定义,因为'this'引用'event.target'

是的,函数的上下文(仅)取决于它的调用。您需要使用

 var that = this;
 ….addEventLister(…, function(event) {
      that.onMouseClick(); // "that" references the instance
 });