- 浏览: 112231 次
- 性别:
- 来自: 济南
文章分类
最新评论
-
tuposky:
请教楼主,怎么在line 或 Circle 里面加一个titl ...
svg DOM的一些js操作 -
tuposky:
good...真全
svg DOM的一些js操作 -
温柔企鹅:
功力太浅,表示压力很大!
ExtJS中ajax回调函数,关于scope和createDelegate() -
jie523314:
miracletree 写道 好!太感谢你了
在ModalDialog中操作父窗口对象 -
miracletree:
好!太感谢你了
在ModalDialog中操作父窗口对象
定义
作用域scope
1.(名词)某样事物执行、操作、拥有控制权的那么一个区域 [1]
2. (名词) 编写程序时,程序之中变量的可见度;例如,一个函数能否使用另外一个函数所创建的变量。[2]
可是这能够说明什么问题呢? 每当有人在说“这是作用域的问题”或“作用域搞错了”的时候,那就是说某个函数运行起来的时候,找不到正确变量的位置。这样我们便知道应该从哪一方面入手,查找出问题所在。
正式开始
实际上每一个你定义的函数都是某个对象的方法。甚至是这样的写法:
function fn() {
alert(11);
}
老兄你不是故弄玄虚吧~。做一个这样的演示可真得是简单得要命。没错!本例不需要任何Javascript文件,服务器或html。你只要打开 firefox,弹出firebug,点击console tab。在Firefox状态栏上面看到有>>>提示的地方就可以输入了。
输入:
function fn() { alert(11); };
然后回车。一切安然...你刚才做的实际上是定义了一个函数fn。接着试试:
fn();
然后回车。得到11的警告窗口?还不错吧?接着试试:
window.fn();
this.fn();
得到一样的结果吧?这是因为函数fn是window对象的一个方法,在第二行的"this"的作用域实际指向了window对象。不过多数情况中你不需要像这样window.myFunction(...)地调用函数,这样太麻烦了,程序员工作起来会很不方便。
window对象
window 对象总是存在的,你可理解其为一个浏览器窗口对象。它包含了其它所有的对象如document 和所有的全局变量。
你可以打开Firebug,切换到 Script 页面并在Firebug右侧的New watch expression... 里面输入 window。观察window对象究竟有什么在里面。
接着,尝试找出我们之前定义过的fn函数。
另外,每个frame或iframe拥有其自身的window对象,其自身的全局空间。
理解作用域
接下的内容开始有点复杂了。切换到Firebug Console标签页然后输入:
var o1 = {testvar:22, fun:function() { alert('o1: ' + this.testvar); }};
var o2 = {testvar:33, fun:function() { alert('o2: ' + this.testvar); }};
结果是什么?你声明了o1 和 o2两个对象,分别都有一些属性和方法,但值不同。
接着试试:
fun();
window.fun();
this.fun();
出错了,是吧?因为window对象(等价于this)并没有fun的方法。试一试下面的:
o1.fun();
o2.fun();
22和33出来了?非常好!
接下来这部分的内容最复杂啦。基于这个原始的函数,如果对象的数量多的话,你必须为每个对象加上这个函数-明显是重复劳动了。这样说吧,o1.fun写得非常清晰的而且为了搞掂它已经占用了我一个星期的开发时间。想象一下代码到处散布着this变量,怎么能不头疼?如果要将调用(执行)的o1.fun方法但this会执行o2,应该怎么实现呢?试一试下面的:
o1.fun.call(o2);
明白了吗?当执行o1的fun方法时你强行将变量this指向到o2这个对象,换句话说,更加严谨地说:o1.fun的方法在对象o2的作用域下运行。
当运行一个函数,一个对象的方法时,你可将作用域当作this值的变量。
变量的可见度
变量的可见度和作用域的关系非常密切。我们已经了解到,可在任何对象的外部,声明变量,或在全局的函数(函数也是变量的一种)也可以,更严格说,它们是全局对象window的属性。 全局变量在任何地方都可见;无论函数的内部还是外部。如果你在某一个函数内修改了一个全局变量,其它函数也会得知这个值是修改过的。
对象可以有它自己的属性(像上面的testvar),这些属性允许从内部或是外部均是可见的。试:
alert(o1.testvar); // 从外部访问o1的属性testvar
从内部访问的演示可在两个测试对象的fun方法找到。
用关键字var在内部声明,相当于声明局部变量(局部声明也是在一条链上,即Scope Chain 作用域链上,Frank注):
i = 44;
function fn2() {
var i = 55;
alert(i);
}
fn2();
将得到什么?对了,55。声明在函数fn2的变量i是一个本地变量(局部变量),和等于44的全局变量i 44没什么关系。 But:
alert(i);
这会访问全局变量i,显示44。
希望本文能帮助读者彻底理解作用域变量可见性的含义。
嵌套的函数(作用域链)
当你进行函数的嵌套时,要注意实际上作用域链是发生变化的,这点可能看起来不太直观。你可把下面的代码置入firebug监视值的变化。
var testvar = 'window属性';
var o1 = {testvar:'1', fun:function(){alert('o1: '+this.testvar+'<<');}};
var o2 = {testvar:'2', fun:function(){alert('o2: '+this.testvar);}};
o1.fun();'1'
o2.fun();'2'
o1.fun.call(o2);'2'
这是本文的首个例子。
var testvar = 'window属性';
var o3 = {
testvar:'3',
testvar2:'3**',
fun:function(){
alert('o3: '+this.testvar);//'obj3'
var inner = function(){
alert('o3-inner: '+this.testvar);//'window属性'
alert('o3-inner: '+this.testvar2);//undefined(未定义)
};
inner();
}
};
o3.fun();
这里我们换了别的函数,这个函数与原先的函数几乎相似但区别是内部函数的写法。要注意的是内部函数运行时所在的作用域,和外部函数的作用域是不一样的。Ext可让你调用函数时指定函数的作用域,避免作用域的问题。
变量的声明
初始化变量时一定要加上“var”关键字,没有的话这就是一个全局变量。譬如,在下面的例子中,会有一个变量写在函数内部,然而你打算仅仅是声明局 部的变量,但实际也可能出现覆盖全局变量的值的情形。在FIREBUG "DOM"的标签页中,你可通过检测“window”看到所有的全局变量。如果你发现有“k”或“x”变量那证明你把这个变量分配在一个不合适的作用域里 面。见下例:
var i = 4;
var j = 5;
var k = 7;
var fn = function(){
var i = 6;
k = 8;//注意前面没有var 所以这句话的意思的把8赋予到变量k中去!
alert(i);//6
alert(j);//5
alert(k+'-1');//8-1
x = 1;//这句的作用有两种情况,创建全部变量x或覆盖(overwrite)全部变量x
};
fn();
alert(k+'-2');//8-2 (注意不是7-2)
与前面例子变化不大,另外注意的是函数内的k前面是没有var关键字的,所以这里不是声明局部变量,而是将某个值再次分配到k这个全局变量中。另外要注意的是,alert方法执行期间,参数i是当前能找到的局部变量,它的值是6,但参数j在当前作用域找不到,就沿着作用域链(scope chain)向上查找,一直找到全局变量的那个j为止。
在Ext中指定作用域
前面已提及,当调用函数时Ext能灵活处理作用域的问题。部分内容来自dj的帖子。
调用函数时,你可以把this想象为每个函数内的一个特殊(躲起来的)参数。无论什么时候,JavaScript都会把this放到function内部。它是基于一种非常简单的思想:如果函数直接是某个对象的成员,那么this的值就是这个对象。如果函数不是某个对象的成员那么this的值便设为某种全局对象(常见有,浏览器中的window对象)。下面的内部函数可以清晰的看出这种思想。
一个函数,若是分配到某个变量的,即不属于任何对象下的一员,那么this的参数就变为windows对象。 下面是一个例子,可直接粘贴到Firebug的console:
var obj = {
toString:function(){ return 'obj的范围内(作用域内)';}, //重写toString函数,方便执行console.log(this)时的输出
func: function(){
// 这里的函数直接从属与对象"object"
console.log(this);
var innerFunc = function(){
//n这里的函数不是特定对象的直接成员,只是另外一个函数的变量而已
console.log(this);
};
innerFunc();
}
};
obj.func();
// 输出 "obj的范围内(作用域内)"
// 输出 "Window的一些相关内容..."
缺省下是这样调用一个参数的-但你也可以人为地改变this参数,只是语法上稍微不同。 将最后一行的"obj.func();" 改为:
obj.func.call(window);
// 输出 "Window的一些相关内容..."
// 输出 "Window的一些相关内容..."
从上面的例子中可以发现,call实际上是另外一个函数(方法)。call 属于系统为obj.func内建的方法(根据JavaScript之特点可得知,函数是一种对象。)。
通过这样改变this指向的作用域,我们可以继续用一个例子来修正innerFunc中的this参数,——“不正确”的指向:
var obj = {
toString:function(){ return 'obj的范围内(作用域内)';}, //重写toString函数,方便执行console.log(this)时的输出
func: function(){
// 这里的函数直接从属与对象"object"
console.log(this);
var innerFunc = function(){
//n这里的函数不是特定对象的直接成员,只是另外一个函数的变量而已
console.log(this);
};
innerFunc.call(this);
}
};
obj.func();
// 输出 "obj的范围内(作用域内)"
// 输出 "obj的范围内(作用域内)"
Ext的作用域配置
可以看到,没有分配作用域的函数,它的this"指向的是浏览器的window对象(如事件句柄event handler等等),——除非我们改变this的指针。Ext的很多类中 scope是一个配置项(configuration)能够进行指针的绑定。相关的例子参考Ajax.request。
Ext的createDelegate函数
*除了内建的call/apply方法,Ext还为我们提供-- 辅助方法createDelegate。 该函数的基本功能是绑定this指针但不立刻执行。传入一个参数,createDelegate方法会保证函数是运行在这个参数的作用域中。如:
var obj = {
toString:function(){ return 'obj的范围内(作用域内)';}, //重写toString函数,方便执行console.log(this)时的输出
func: function(){
// 这里的函数直接从属与对象"object"
console.log(this);
var innerFunc = function(){
//n这里的函数不是特定对象的直接成员,只是另外一个函数的变量而已
console.log(this);
};
innerFunc = innerFunc.createDelegate(this); // 这里我们用委托的函数覆盖了原函数。
innerFunc(); // 按照一般的写法调用函数
}
};
obj.func();
// 输出 "obj的范围内(作用域内)"
// 输出 "obj的范围内(作用域内)"
这是一个小小的例子,其原理是非常基本基础的,希望能够好好消化。 尽管如此,在现实工作中,我们还是容易感到迷惑,但基本上,如果能按照上面的理论知识去分析来龙去脉,万变还是不离其中的。
另外还有一样东西,看看下面的例子:
varsDs.load({callback: function(records){
col_length = varsDs.getCount();//这里的varDs离开了作用域?
//col_length = this.getCount();//这个this等于store吗?
for (var x = 0; x < col_length; x++)
{
colarray[x] = varsDs.getAt(x).get('hex');
}
}});
不过可以写得更清晰:
var obj = {
callback: function(records){
col_length = varsDs.getCount();//这里的varDs离开了作用域?
//col_length = this.getCount();//这个this等于store吗?
// ...
}
};
varsDs.load(obj);
现在函数callback直接挂在obj上,因此this指针等于obj。
但是注意: 这样做没用的。为什么?因为你不知obj.callback最终执行时发生什么情形。试想一下Ext.data.Store的load方法(仿造的实现):
...
load : function(config) {
var o = {};
o.callback = config.callback;
//进行加载
o.callback();
}
...
这个仿造的实现中,回调函数的作用域是私有变量“o”。 因为通常你无法得知函数是如何被调用的,如果不声明作用域,你很可能无法在回调函数中使用this参数。
原文出处:http://extjs.com/learn/Tutorial:What_is_that_Scope_all_about_(Chinese)
感谢作者
发表评论
-
svg DOM的一些js操作
2012-07-16 16:55 7219这是第一个实例,其中讲了如何新建svg,添加元素,保存s ... -
如何动态引入外部Javascript文件
2012-05-16 17:00 1226<html> <head> ... -
ExtJS中ajax回调函数,关于scope和createDelegate()
2011-05-02 15:33 3837关于JavaScript中this的使用,这是一个由来已久 ... -
ext ref
2011-04-29 20:15 2212Ext3.x的ref是个不错的东东,可以省了不少getCmp( ... -
js this
2011-04-29 09:51 979Java代码 ... -
Ext智能提示 - Spket(Eclipse插件)
2011-04-14 09:47 1090Eclipse的Ext 2.0.2智能提示.它提供了非常准确的 ... -
extend
2011-04-11 10:13 865extend (Object subclass,Object ... -
如何控制页面内容的加载顺序
2009-07-09 00:31 1181目前网站之间相互调用的情况越来越多,比如 需要调用某个第三方提 ... -
通过js操作select标签的onclick事件
2009-05-07 11:10 5190<html> <body> < ... -
js数组的完整说明
2008-12-22 21:28 1464使用数组 基本操作 <script> va ... -
js 数组对象的操作方法
2008-12-15 22:36 2065注意:以下是按操作来分类的,有的方法有多个用途,就有重复 1、 ... -
常用表单基本取值方法
2008-10-23 14:53 1040一.常用表单基本取值方法(form1为表单名称,Text ... -
javaScript DOM方法与属性摘要
2008-10-22 13:57 9671 createElement(element) 创建一个指定 ... -
js动态操作表格
2008-10-22 10:16 3293一. 动态为obj表格增加一行 function add ... -
showModalDialog和showModelessDialog
2008-10-21 21:19 900showModalDialog和showModelessDia ... -
在ModalDialog中操作父窗口对象
2008-10-21 21:16 15411、不能使用window.parent Window.pare ...
相关推荐
通过这个 "sample-javascript-documentation-jsduck-extjs-master" 压缩包,我们可以学习如何配置和运行 JSDuck,以及如何编写有效的文档注释,以便为 ExtJS 项目自动生成文档。 在使用 JSDuck 之前,我们需要确保...
ExtJS 是一个强大的JavaScript库,专门用于构建富客户端Web应用程序。在标题"extjs2----关于extjs 的使用,操作"中,我们可以看出这是一份关于ExtJS 2.0版本的使用指南,主要涵盖了其基本操作和应用。描述中提到内容...
eslint-plugin-extjs 使用ExtJS框架的项目的ESLint规则。 这些规则的目标是与ExtJS 4.x一起使用。 欢迎请求与5.x兼容的请求! 规则明细 ext-array-foreach ExtJS提供的两个主要的数组迭代器函数和不同之处在于, ...
这个压缩包“struts2-hibernate-spring-Extjs-json.rar”显然包含了关于这些技术整合使用的参考资料。下面将详细阐述这些技术以及它们之间的交互。 1. **Struts2**: Struts2是一个基于MVC(模型-视图-控制器)...
一个extjs的OA项目 extjs-OA extjs-oaextjs-OA extjs-oa
从中解压出features与plugins文件夹,复制到E:\MyEclipse\myPlugins\spket-1.6.23里面 在E:\MyEclipse\MyEclipse 10\dropins下新建文件spket-1.6.23 .link,内容是:path=E:\\MyEclipse\\myPlugins\\spket-1.6.23 保存...
Extjs6.2 生成的admin-dashboard官方模板
在给定的标题"JavaScript libraries--->jQuery, Prototype, Mootools, YUI, Extjs, Dojo"中,提到了五种著名的JavaScript库:jQuery、Prototype、Mootools、YUI和ExtJS。这些库都有各自的特性和优势,下面将详细介绍...
Extjs4.0学习笔记,以下是部分介绍: xtjs4,创建Ext组件有了新的方式,就是Ext.create(....),而且可以使用动态加载JS的方式来加快组件的渲染,我们再也不必一次加载已经达到1MB的ext-all.js了,本文介绍如何在EXTJS4...
ExtJS 4 DirectStore post参数的变化以及应对方法 ExtJS 4 实例之数据包 ExtJS 4中动态加载的路径设置 Extjs4 API文档阅读(一)——类系统(Class System) Extjs4 API文档阅读(三)——布局和容器 Extjs4 API文档阅读...
ExtJS是一个用于构建富客户端应用的JavaScript库,提供了丰富的组件和布局管理,可用于创建复杂的用户界面。ExtJS4支持数据绑定、远程数据交互(通过Ajax)等功能,使得开发者可以轻松构建动态、交互性强的Web应用。...
first-extjs-parent"的子项目应该按照Maven的约定进行目录结构的组织,如src/main/java存放Java源代码,src/main/resources存放资源文件,src/main/webapp存放Web应用相关的资源,如HTML、CSS、JavaScript等。...
离线API和该文章pdf文件 博文链接:https://yongtree.iteye.com/blog/199588
ExtJS是一个流行的JavaScript库,用于构建富客户端的桌面级Web应用,它提供了丰富的组件库,包括表格、窗口、面板等,使得开发者能够构建出具有高度交互性和美观界面的应用。 在ResviewCRM的源码中,我们可以看到...
ext-4.0.7-gpl官方发布包,开发源代码 各种例子
ext-4.2.1ext-4.2.1ext-4.2.1ext-4.2.1ext-4.2.1ext-4.2.1ext-4.2.1
extjs-4.1.1 ExtJs所有文档及库文件,在官网下的,这个版本很好,放在这方便大家下载!