Extjs4 Web Application Development Cookbook学习笔记四

8 篇文章 0 订阅
7 篇文章 0 订阅
[color=red][u][b]原创翻译,欢迎纠错,转载请注明出处[/b][/u][/color]

[b]4.函数作用域[/b]
Javascript开发者面临的一个很大的问题就是函数作用域的问题,因为this在js中是随着函数不同而变化的,并不像java类中指向全局。每个函数内部的this都是不同的。
强烈建议先学习下js的作用域规则(参见《Javascript权威指南》),这里我们将简要介绍作用域是什么?怎么变化?对我们的代码有什么影响?

[b]a.什么是函数作用域Scope[/b]
作用域指的是一段正在执行的代码的上下文环境,他决定了什么样的变量对其是可用的。
js有两种类型的作用域:全局作用域和局部作用域。全局作用域下定义的函数和变量在任何地方都是可以访问的。最常见的例子是document和window变量。局部变量和函数是指在一个函数内部定义的,不能被函数外部访问。
作用域链是js解析变量的一种方式,当试图访问一个函数中的变量时,如果这个变量不是在函数内定义的,那么js引擎将遍历作用域链(函数链 原型链)找到与之同名的变量,如果没有则抛出一个错误,这意味着局部的变量会优于全局变量被找到和使用。

下面我们将举几个例子说明作用域是什么工作的

1.第一个例子很简单,我们声明一个全局变量,并通过alert访问它
var myVar = 'Hello from Global Scope!';
alert(myVar); //alerts 'Hello from Global Scope!'


2. 下面这个例子会弹出两个alert,第一个打印Hello from Global Scope!,第二个打印Hello from MyFunction!,说明在函数myFunction中可以访问和修改全局变量
var myVar = 'Hello from Global Scope!';
function myFunction(){
myVar = 'Hello from MyFunction!';
}
alert(myVar); //alerts 'Hello from Global Scope!'
myFunction();
alert(myVar); //alerts 'Hello from MyFunction!'


3. 我们在myFunction中定义一个局部变量myVar,这样局部变量myVar的作用域是函数myFunction,这样在执行alert(myVar)时将会打印出Hello Global Scope!而不是Hello from MyFunction!,因为这样是相当于在函数内部定义了一个局部变量而不是改变了全局变量的值,且函数外面的alert也不能访问到函数中的myVar变量。而函数中的alert访问的就是函数中定义的myVar了,根据上面说的,他会先访问局部变量。
var myVar = 'Hello Global Scope!';
function myFunction(){
var myVar = 'Hello from MyFunction!';
alert(myVar);
}
alert(myVar); //alerts 'Hello from Global Scope!'
myFunction(); //alerts 'Hello from MyFunction!'
alert(myVar); //alerts 'Hello from Global Scope!'

4. 最后我们将演示this关键字的用法,this关键字无处不在,为我们提供了一个访问当前代码执行的上下文环境的引用。下例中使用MyClass的构造器新建一个对象,通过观察log中的this值发现其实新建对象的引用,这意味中我们可以在这个对象上定义属性,并使得他们的作用域只在这个对象内部,不会被对象外部访问到。
function MyClass(){
console.log(this);
}
var myClass = new MyClass();

5. 如果我们在构造器中添加一个属性,当对象创建后我们可以在构造器中将其alert出来,但是如果我们试图在MyClass作用域外访问this.myProperty,他将不存在,因为这里的this指的是浏览器对象window。

function MyClass(){
console.log(this);
this.myProperty = 'Hello';
}
var myClass = new MyClass();
alert(myClass.myProperty); // alerts 'Hello'
alert(this.myProperty); // alerts 'undefined'


[b]ExtJs中的作用域[/b]

在Extjs中我们需要关心的是确保我们的函数在正确的类的作用域中执行。例如默认情况下Button的点击事件的作用域是自身,而如果我们想要他的handler事件在其父类中执行,例如grid Panel中,则需要将作用域scope指定到grid panel。
下面通过几个例子看一下extjs是怎么做的

1. 定义两个对象,每一个都有一个属性和方法。

var cat = {
sound: 'miaow',
speak: function(){
alert(this.sound);
}
};
var dog = {
sound: 'woof',
speak: function(){
alert(this.sound);
}
};
cat.speak(); // alerts 'miaow'
dog.speak(); // alerts 'woof'


2. 使用 Ext.bind 方法强制使得dog对象的speak方法在cat对象中执行
Ext.bind(dog.speak, cat)(); // alerts 'miaow'


[b]工作原理[/b]
Ext.bind方法通过创建包装函数,重写了speak方法的作用域,强制 赋为传进来的第二个参数,使得这个新的函数能够立即执行或者存储在一个变量中稍后执行。通过使用bind函数我们重新定义this为函数传入的第二个参数,这就是为什么上例2中执行狗狗的speak方法会发出猫咪的叫声。

[b]More[/b]
对于事件处理函数来说确保函数的作用域正确是尤其重要的。Extjs提供了一个scope的配置项可用于设置事件处理函数执行的作用域。
例如下例中,我们定义了一个button和一个click事件,点击click后会弹出一个alert,显示当前作用域下的text属性值。

var button = Ext.create('Ext.button.Button', {
text: 'My Test Button',
listeners: {
click: function(button, e, options){
alert(this.text);
}
},
renderTo: Ext.getBody()
});
button.show();

默认情况下,this指向button本身,但是如果我们想要这个函数在另一个作用域中执行,例如在下面的作用域中执行。
var exampleObject = { text: 'My Test Object'};

我们最初吃的反应是使用bind方法,如下

listeners: {
click: Ext.bind(function(button, e, options){
alert(this.text);
}, exampleObject)
}

上面的方法执行的很好,功能也正确,不过我们有更简单的方法,通过配置scope实现。

listeners: {
click: function(button, e, options){
alert(this.text);
},
scope: exampleObject
}

如果你在listeners中配置scope,那么对于所有的事件都会生效,如果只想针对某个事件指定其scope,可以这样写:

listeners: {
click: {
fn: function(button, e, options){
alert(this.text);
},
scope: this
},
afterrender: {
fn: function(button, options){
// do something...
},
scope: otherObject
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值