自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
在JavaScript中函数本身也是一个Function实例。请看如下示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
var add=function (a,b){
var c=a+b;
document.writeln(a+"+"+b+"="+c+"
");
}
add(9526,1);
var result=add instanceof Function;
document.writeln("函数是否是Function类的实例? ----> "+result+"
");
script>
body>
html>
运行后效果如下图所示:
所以,从这里也可再次印证:在JavaScript中函数本身也是一个对象,既然是对象那么它就拥有相应的属性和方法。故,在此介绍几个Function中非常常用的属性和方法。
Function的length属性返回函数的输入参数的个数
Function的arguments代表正在执行的函数的内置属性,它包含了调用该函数时所传入的参数信息。例如:可使用arguments.length得到参数的个数;可利用arguments[index]得到参数的值。
Function的prototype属性保存着函数的原型对象。在英语中单词prototype的意思是"样机",假若你把样机都改了,那么之后以此为蓝本的生产的产品也会随之发生变化。嗯哼,顺着这个单词的本意,我们来看如下示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
function Dog(name,color){
this.name=name;
this.color=color;
this.type="犬科";
this.eat=function(){
document.writeln("Dog eat bone"+"
");
}
}
var xiaobai=new Dog("小白","白色");
xiaobai.eat();
var xiaohei=new Dog("小黑","黑色");
xiaohei.eat();
script>
body>
html>
定义一个Dog类,Dog具有三个属性:名字,颜色,类别;Dog还有一个方法eat( )。建立两个对象xiaobai和xiaohei再调用其eat( )方法,输出结果如下:
采用该方式来创建对象,可以是可以;但是带来一个弊端:代码的冗余和内存的浪费。比如,在该示例中每生成一个实例,都会重复生成type属性和eat( )方法从而浪费了内存。这时候,prototype(原型对象)就派上用场了。在JavaScript中实例可继承prototype的属性和方法;也就是说:我们可把那些不变的属性和方法直接定义在prototype对象上。现在就利用prototype修改刚才的示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
function Dog(name, color) {
this.name = name;
this.color = color;
}
Dog.prototype.type = "犬科";
Dog.prototype.eat = function() {
document.writeln("Dog eat bone" + "
");
}
var xiaobai = new Dog("小白", "白色");
xiaobai.eat();
var xiaohei = new Dog("小黑", "黑色");
xiaohei.eat();
script>
body>
html>
在此从结构和效率的角度优化代码,将type属性和eat( )方法定义在了prototype中。
接下来,我们再在Array的prototype添加一个找出最大值的方法getMax。
代码如下:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>prototype示例title>
head>
<body>
<script type="text/javascript">
Array.prototype.getMax = function() {
//this代表当前对象
var max = this[0];
for (var index = 1; index < this.length; index++) {
if (this[index] > max) {
max = this[index];
}
}
return max;
}
var arr = [62, 44, 17, 9];
var max = arr.getMax();
document.write("最大值是:" + max);
script>
body>
html>
结果如下:
最大值是:62
其实,从这个角度来看prototype多少有点Java中继承的味道。
call( )和apply( )用于调用当前Function对象并与此同时改变函数内的this指针引用。换句话说:call( )和apply( )切换了函数执行时的上下文(this值)。call( )和apply( )是Function对象的方法,每个函数都能调用它们。先来瞅瞅call( )
请看如下示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
var name="小明";
var boy={name:"大雄"};
function introduce(message){
document.writeln(message+",我的名字是"+this.name+"
");
}
introduce("hello");
introduce.call(this,"hello");
introduce.call(boy,"大家好");
script>
body>
html>
在该示例中,有个变量name,有个对象boy;还有一个函数introduce( ),在该函数中用this.name表示当前环境下的name的值,默认情况下该值为"小明"
直接调用introduce( ),请参见代码第14行
在这种情况下函数introduce( )中的this.name就是指的"小明",这个大家都明白,不再多说。
调用introduce.call(this,“hello”),请参见代码第15行
这句代码和直接调用introduce( )没多大的区别,只不过明确了上下文环境为this而已。
调用introduce.call(boy,“大家好”),请参见代码第16行
在此利用call( )切换了执行introduce( )时的上下文环境,此时相当于是boy在调用introduce( ),所以中introduce( )的this指向的是boy对象,this.name就是boy对象中的name
运行后,输出结果如下图所示:
嗯哼,看到这,可能有人对于call还是有些费解,觉得这个玩意有点不太好理解。没事儿,别担心,我们再来看个例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
var name = "小明";
function introduce(message) {
document.writeln(message + ",我的名字是" + this.name + "
");
}
var boy = {
name: "大雄",
introduce: function(message) {
document.writeln(message + ",我的名字是" + this.name + "
");
}
};
introduce("hello");
boy.introduce("大家好");
script>
body>
html>
嘿嘿,请看这个例子:先定义了一个方法introduce(message),然后定义boy对象,并且在该对象中也有一个完全相同的方法introduce(message)。嗯哼,累不累?繁琐不?已经有了为什么还要做重复的工作?站在这个角度可以更好地体会call( )。其实,这也是JavaScript中继承的雏形。
apply( )与Function对象的call( )函数作用相同,只不过call( )函数是将Function对象的参数一个个分别传入,而apply( )函数是将Function对象的参数以一个数组或以arguments对象的形式整体传入。其余东西,不再赘述。
在这几篇文章中我们学习了JavaScript的函数,类,对象。在此,对这三者的关系做一个梳理和小结。
在JavaScript中在定义函数的同时会得到一个与之同名的类。请看如下示例:
函数与类
代码详解如下:
定义函数Student,请参见代码第9-15行
在此定义一个函数的同时得到一个Student类
利用Student创建对象s,请参见代码第16行
调用对象s中的方法,请参见代码第17行
运行后效果图如下所示:
所以,简单地来说:函数名就是类名,函数本身就是类的构造函数,并且可以使用new关键字创建一个实例对象。
在JavaScript中几乎所有东西都是对象;包括我们刚才讲的函数,它本身也是Function的实例!
这几篇文章中我们多次用到JavaScript的关键字this,或许有的童鞋在看到这个玩意儿时有点懵。
this?对象?不解啊!啥玩意儿啊!在JavaScript中this指的是调用该函数的对象。在利用构造函数生成一个新对象(object)的过程中this指的就是这个新对象!现在,我们再回过头来看几行已经非常熟悉的代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>函数title>
head>
<body>
<script type="text/javascript">
var name="小泽";
function print(){
document.writeln(this.name);
}
print();
script>
body>
html>
在该示例中:有个变量name,该变量默认属于window。除此以外,还有一个函数print( )。在代码第13行执行了:
print();
嗯哼,请问是谁调用了函数print( )???是window!!!所以,你写成window.print( )也是完全没有错误的。那么,在print( )方法中document.writeln(this.name);这里的this当然指向了window,所以this.name表示了window的name.