Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript-从函数的局部范围内获取变量_Javascript - Fatal编程技术网

Javascript-从函数的局部范围内获取变量

Javascript-从函数的局部范围内获取变量,javascript,Javascript,除了基本的javascript之外,我对任何东西都不擅长,所以请原谅这个简单的问题 我正在使用图书馆。此库有一个图形对象,其外观如下所示: function jsGraphics(canvasDivElement) { var canvasDiv; this.drawLine = drawLine; function drawLine(point1, point2) { // do things with canvasDiv } } 您可以这样使用它: var gr =

除了基本的javascript之外,我对任何东西都不擅长,所以请原谅这个简单的问题

我正在使用图书馆。此库有一个图形对象,其外观如下所示:

function jsGraphics(canvasDivElement) {
  var canvasDiv;
  this.drawLine = drawLine;
  function drawLine(point1, point2) {
    // do things with canvasDiv
  }
}
您可以这样使用它:

var gr = new jsGraphics(document.getElementById('canvas'))
gr.drawLine(new jsPoint(0,0), new jsPoint(10,10))
我想向jsGraphics添加一个函数,以便调用

gr.getCanvasElement()
有没有一种不用编辑库本身就可以做到这一点的方法

我试过了

jsGraphics.prototype.getCanvasElement = function() { return canvasDiv }

但这似乎不起作用。我有一种直观的感觉,那就是它与新的关键字有关,但如果你能解释为什么它没有,那也会很有帮助。

不,这不是使用普通的基于JavaScript原型的继承,而是向
jsGraphics
的每个实例添加一个单独的
drawLine
函数,每个变量都有一个围绕其自己的canvasDiv变量的闭包


一旦
函数jsGraphics(){
关闭
}
就根本无法访问canvasDiv变量,除非其中的一个函数提供对它的访问。这通常是有意地创建私有变量,明确地阻止您访问canvasDiv。

您不可能只访问canvasDiv元素,因为如果从未使用This关键字将其分配给构造函数中的对象,对该对象的引用存在于构造函数本身创建的闭包中

但是,您可以将构造函数包装在新构造函数中,然后将原型设置为相等:

function myJsGraphics(canvasDivElement) {
  this.canvasDiv = canvasDivElement;
  jsGraphics.call(this, cavasDivElement);
}

myJsGraphics.prototype = jsGraphics.prototype;
现在,您应该能够使用新的构造函数访问元素:

var obj = new myJsGraphics(document.getElementById('blah-elem'));
elem = obj.canvasDiv;
如果你不习惯的话,整个闭包的事情有点奇怪,但要点是在某个特定范围内定义的函数,但在其他地方可以使用,可以引用它们一直在定义的范围内的变量。最简单的示例是当您有一个返回函数的函数时:

function makeIncrementer(start) {
  return function () { return start++; };
}

var inc = makeIncrementer(0);
var inc2 = makeIncrementer(0);
inc(); // => 0
inc(); // => 1
inc(); // => 2
inc2(); // => 0
当函数从makeIncrementer函数返回时,对“start”变量的引用被“关闭”。它不能直接访问。在对象的构造函数中也会发生同样的情况,局部变量被“封闭”到对象的成员函数中,它们充当私有变量。除非构造函数中定义了对私有成员的方法或变量引用,否则您就无法访问它。

这种“私有状态”技术在过去几年中变得越来越惯用。就我个人而言,当我试图从控制台快速调试某些东西或覆盖第三方库中的行为时,我发现它有着奇怪的限制。这是为数不多的几次我想“该死,为什么我不能用语言来做这件事”。当我真的需要快速调试一个“私有变量”时,我已经在Firefox2中进行了很好的利用

我很想知道别人什么时候使用这个成语,或者他们什么时候避免使用这个成语。(@bobince我看着你)

无论如何,@bobince已经基本回答了您的问题(简而言之:不,您不能从您所在的范围访问
canvasDiv
变量)

但是,有一件事你可以做,那就是在破解或编辑第三方库之间进行折衷(我总是选择破解;):你可以扩充对象以保存你知道以后需要的引用

黑客1:如果您自己控制对象实例化:

var canvas = document.getElementById('canvas');
var gr = new jsGraphics(canvas);
gr._canvasDiv = canvas; // Augment because we'll need this later

// Sometime later...

gr._canvasDiv; // do something with the element
如果库支持类似于析构函数的概念(在卸载页面或其他内容时触发),请确保在那里也清空或删除您的属性,以避免IE中的内存泄漏:

delete gr._canvasDiv;
Hack 2:在包含库之后立即覆盖构造函数:

// run after including the library, and before
// any code that instantiates jsGraphics objects
jsGraphics = (function(fn) {
    return function(canvas) {
        this._canvasDiv = canvas;
        return fn.apply(this, arguments)
    }
}(jsGraphics))

然后以
gr.\u canvasDiv
的形式访问元素(现在是公共的)。关于在页面卸载中删除它的同样注意事项也适用。

您是否将
document.getElementById('canvas')
传递给
jsGraphics
?如果你是,你可以调用
document.getElementById('canvas')
来得到同样的东西
canvasDiv
可以。我想要的不是真正的canvasDiv,而是它的宽度/高度,它将用于我计划添加的一些简化外观方法中。页面本身将有许多jsGraphics对象,但是我需要依次处理每个对象。真的吗?我认为javascript中的任何东西都是可能的……从技术上讲,我想把它当作一个受保护的变量,在一些方法中使用,如果这能让它变得更容易的话,我会在将来添加。是的,我比较喜欢调试友好的Python方法,您可以将其设置为
this.\u canvasDiv
,任何使用以下划线开头的变量的人都会遇到麻烦,除非他们是成员函数(或者他们真的知道自己在做什么)。但是,这需要您更改构造函数.jsGraphics.call(This);应该是jsGraphics.call(this,canvasDivElement);