什么是Titanium的“proxy”对象?

【官方地址】[url=http://developer.appcelerator.com/blog/2012/02/what-is-a-titanium-proxy-object.html]http://developer.appcelerator.com/blog/2012/02/what-is-a-titanium-proxy-object.html[/url]

如果你经常关注我们的开发Blog,而且阅读了我们基于wiki的文档,你可能会多次看到过“proxy对象”的说法。简单来说,proxy是一个特殊的JavaScript对象,用来代替原生(iOS或者Android,在mobile web是不需要这个)代码的相应对象。

//这里的"button"就是一个proxy对象
var button = Ti.UI.createButton({
title:'push me!',
height:50,
width:200
});


如果你想详细的知道什么是proxy?它如何工作的?可以查看Module开发指南,它详细讲解了为iOS或者Android开发你自己Module的整个过程。

任何时候你访问Ti.* JavaScript命名空间中的函数或者属性,或者使用从这个命名空间的函数返回的对象时,这个对象就是某种类型的proxy。

为了更好的实现JavaScript Conext和原生代码的“桥接”,这些proxy对象被赋予了特殊的功能:允许原生代码(Java, C, 或Objective-C)拦截对象的分配以及函数的调用。这种交互的模式允许开发者能使用JavaScript编写原生代码,使Titanium有别于许多其他跨平台工具。

[b]Proxy是特殊的[/b]
作为Titanium平台的使用者,理解这些对象的是很有帮助的,至少在Titanium1.X或者可能在Titanium2.X的很长一段时间里,proxy对象不会总是顺从JavaScript的规则。那么让我们来看看一些没有延续JavaScript规则的地方。

[b]嵌套对象[/b]
对于普通的JavaScript对象,你可以为对象(只要这些属性对象存在)设置嵌套属性,比如“meaning.of.life = 42;”,但对于Proxy对象来说是不可以的。一个比较有代表性的例子,你会用到Label的“font”属性,比如如下例子中,“l”是一个Proxy对象,它有一个内嵌的属性“font”,然后为它设置 fontSize。当我们试着直接给它设置嵌套属性fontSize的时候,它是不能够运行的,而是必须设置整个font对象给这个值。

var w = Ti.UI.createWindow({
backgroundColor:'white'
});

var l = Ti.UI.createLabel({
text:'here is a label',
font: {
fontFamily:'Trebuchet MS'
}
});
w.add(l);

//运行不了
l.font.fontSize = 24;

//可以正常运行
l.font = {
fontFamily:'Trebuchet MS',
fontSize: 24
};

w.open();


[b]覆盖属性[/b]
Proxy对象的另外一个特殊地方是,对于作为proxy对象的公开接口的函数(Titanium预定使用函数和属性)是不能被复写的。以下是一个典型的例子:

var window = Ti.UI.createWindow({
backgroundColor:'red'
});

window.open = function() {
alert('overriding open!');
};

window.open();

当你运行这段代码时,你会发现,“open”是Proxy对象的一个公共接口函数,我们写得代码只是残留着,并不是我们想想的这个函数被覆盖了。

[b]Getters 和 Setters[/b]

特殊的函数名有他们特殊的用处。任何以“get”和“set”开头的函数都被委托给原生代码,所以任何你想设置给Proxy的自定义getter和setter都将会被忽略。

var window = Ti.UI.createWindow({
backgroundColor:'red'
});

window.getSomething = function() {
alert('getter function');
};

window.setSomething = function(something) {
alert('trying to set '+something);
};

window.open();

//被忽略
window.getSomething();
window.setSomething('foo');


[b].apply 和.call[/b]

一般你可以使用JavaScript的.apply 和.call的来调用函数,因为函数是一个类对象。但是对于Titanium的Proxy对象来说,由于其有着特殊的构造,是不允许这样被调用的。以下代码虽然是合理的,但是运行之后会出错。
var window = Ti.UI.createWindow.call(this,{
backgroundColor:'red'
});
window.open();


[b]包装Proxy[/b]

有时候这种行为比较烦人,因为对于Ti.*命名空间下的对象,我们想使用JavaScript的所有技巧。当我们使用Proxy处理问题时,一般我们都是在普通的JavaScript对象中包装一个Proxy对象,不直接访问原生Proxy。比如下边这个简单的例子,他可以放到Titanium的根目录下。

Resources/WrappedWindow.js

//Proxy wrapper
function WrappedWindow(args) {
this.proxy = Ti.UI.createWindow(args);
}

WrappedWindow.prototype.open = function(args) {
this.proxy.open(args);
};

WrappedWindow.prototype.setBackgroundColor = function(color) {
//this works because WrappedWindow is just a plain ol' JS object!
this.proxy.animate({
backgroundColor:color,
duration:4000
});
};

module.exports = WrappedWindow;


Resources/app.js

var WrappedWindow = require('WrappedWindow');

var w = new WrappedWindow({
backgroundColor:'white'
});

w.open();
w.setBackgroundColor('red');


使用这个技巧,你可以避开Proxy对象的特殊行为,因为直接操作他们是很麻烦的。

[b]总结[/b]

Proxy对象是你使用JavaScript编写原生代码的一个桥梁。然而他们有一些特殊的规则适用于他们。需要特别注意的是:

[list][*]不能设置嵌套属性
[*]不能复写Proxy对象公开API的属性
[*]以“”和“”开发的函数是被拦截的
[*]Proxy对象的.call 和 .apply是不能运行的
[/list]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值