多数码农会用javascript,但是编程的用法类同Java、C#、C++之类的面向对象编程语言。看了我们的开源实例,提出一些很好的问题,现一一作答。
问:为什么你们写的js,有些地方看上去有点怪?
答:js不是个面向对象的语言,其实是一种函数编程语言,function programming language。javascript的设计参考了Scheme,函数成为第一要素,这不是大家的习惯,看上去会有点怪。然而理解并不难,例如:
var f = function(x) {
return x * x;
};
var y = f(5);
alert(y); // 显示5的平方25
也就是说,一个函数可以像数据那样赋值给一个变量,然后用变量来调用函数。C++里面支持指向函数的指针,道理一样,但是js的写法要方便太多,你可以不给函数起名字定义它。例子中的函数是个匿名函数。如果我写 var n = 357; 你说我需要给数值357起个名字吗?既然函数能当成普通数据,自然不起名字最方便。javascript的另一个基本要素是object。例如:
var product = {
name: "包装盒子",
length: 5,
height: 7,
width: 10,
weight: function(unit_weight) {
var volume = this.length * this.height * this.width;
return unit_weight * volume;
}
}
这个object对象里,有5个变量字段,前面是普通的字串和数值,最后的是一个匿名函数。看上去挺像Java Class,你可以把"weight“匿名函数想象成一个方法method。在我们做的每一个页面里,initialize就是一个做初始化的函数。为了方便,你可以添加自己的函数。
问:什么是callback,起什么作用?
答:callback就是回调,并非javascript的专利,做UI编程到处可见。callback是一个函数,例如在教程9里面的startPage页面跳转部分:
context.startPage({
nameSpace : 'dev.views.BasicView_1409727629303', // 页面的命名空间
callback : function (feed) {
// 发布新数据页面的回调
if (feed) {
if (tableView) {
// 添加新数据项到已经存在的数据列表
var row = _this.createRow(feed);
tableView.insertRowBefore(0,row,true);
} else {
// 原先还没有数据列表,创建新的数据列表
queryFeeds();
}
}
}
});
此处回调函数的作用:页面跳转后,当新页面退出时,系统会调用执行这个callback函数。参数是在新页面中新建的数据项,用feed参数到原来的页面,系统自动调用,把新建的数据项添加到页面里。
问:Ti.UI.SIZE是什么效果?
答:Ti.UI.SIZE是一个常量,告诉Ti所桥接的原生UI,尺寸要自动适应。例如一段文字的文本高度可能只有一行,也可能有三行。具体多少行的高度,就让系统来决定具体尺寸。
问:this是做什么用的? 为什么要写 var _this = this ?
答:既然javascript是个函数编程语言,到处是函数。如果函数在一个object对象里,this就能在代码里引用这个对象。例如前面的object中,函数里引用object product用上了this:
var product = {
name: "包装盒子",
length: 5,
height: 7,
width: 10,
weight: function(unit_weight) {
var volume = this.length * this.height * this.width;
return unit_weight * volume;
}
}
此处,this代表了object product。如果不写this.length,javascript的解释器会认为length没有定义,length的数值是undefined,而不是5。
教程9中,第34行是 var _this = this; 第118行在前面讲解callback回调的代码里,用了这个_this:
var row = _this.createRow(feed);
显然,_this是this的一个替身。这是因为我们要调用页面Object里面的createRow函数。然而callback的函数嵌套在页面函数里,callback函数内部,如何写this,javascript解释器会认为引用当前函数所在的Object,亦即callback所在的做为startPage参数的Object,这样就找不到createRow了。所以我们必须使用一个替身来“记住”页面Object。如果前面没有写替身,还有一个用bind(this)的办法,殊途同归:
context.startPage({
nameSpace : 'dev.views.BasicView_1409727629303',
//发布页关闭时回调此方法,并传回发布的数据
callback : function (feed) {
if (feed) {
if (tableView) {
var row = this.createRow(feed);
tableView.insertRowBefore(0, row, true);
} else {
queryFeeds();
}
}
}.bind(this)
});
此时bind(this)的意思是“绑定这里”,让this绑定到页面的Object上。由于不直观,初学者不建议用此法。
javascript里面的this问题,或许是最难懂的部分。术语叫closure闭包,每个函数有自己的闭包,this永远指向闭包。