好吧,方法和函数
函数是一等公民
函数有点像Java的方法,调用时,也有参数和返回值。但是有一个关键的区别:Java方法天生捆绑在定义它的类上,不能与类脱离开存在;JavaScript函数是自由浮动的实体,自身就可以作为正常等对象(静态的Java方法位于这两者之间——它们并没有捆绑在任何对象实例上,但是仍然捆绑在类的定义上)。
在JavaScript中,Function是一个内建的对象类型。就像期待的那样,它包含可执行的代码,可以调用,但是它也是Object类的子孙,并且可以做JavaScript对象可以做的任何事情,例如使用名称来保存属性。Function对象上很可能(并且非常普遍)附加其他的Function对象作为它的方法。
在单独一行中引用一个函数并且调用它,例如:
var result = MyObject.doSomething(x,y,z)
然而,Function是第一等的对象,它也可以通过call()方法(以及它的近亲apply()方法)来执行:
var result = MyObject.doSomething.call(MyOtherObject,x,y,z)
/*相当于MyObject.doSomething(x,y,z)*/
或者甚至是:
var result = MyObject[‘doSomething’].call(MyOtherObject,x,y,z)
注:Function.call()的第一个参数是在调用期间作为函数上下文使用的对象,随后的参数作为函数调用的参数。apply()的工作方式略微不同,其中第二个参数是一个传递给函数调用的参数数组,允许以编程方式调用那些参数列表长度不确定的函数,这带来了巨大的灵活性。
补充:call()方法来实现继承:
function Class10()
{
……
}
function Class11()
{
……
}
function Class2()
{
Class10.call(this);
Class11.call(this);
}
这样Class2便实现了多重继承,对于call的介绍可上网进一步查看。
JavaScript函数的参数列表的长度不固定。使用比声明更多或者更少的参数来调用一个Java或者C#方法将会产生编译期错误。而JavaScript仅仅忽略任何额外的参数,并且给缺少的参数赋值undefined。一个特别智能的函数可以通过arguments属性查询它自己的参数列表,比起为缺少的值分配明智的默认值,抛出一个异常或者采取任何其他的补救措施。这个特征可以通过将获取和设置方法组合在单个函数中来演示,例如:
function area(value)
{
if(value)
{
this.area = value;
}
return this.area;
}
注:如果简单地调用area(),那么value是未定义的,所以没有发生赋值,函数作为getter方法来使用。如果传入了一个值,函数就作为setter方法来使用。这种技术被Mike Foster的x库广泛使用,所以,如果你计划使用这个库,你很快就会熟悉这个习惯用法。
当我们对函数作为第一等对象的独立性加以利用时,它才变得真正有趣起来。
面向对象附加函数
作为一种函数式语言,JavaScript允许脱离任何对象来定义函数,例如:
function doSomething(x,y,z) {……}
还可以使用内嵌的方式来定义:
var doSomething = function(x,y,z) {……}
函数可以附加到对象上,我们可以将预先定义的函数附加到预先定义的对象上(在这种情况下,只有该对象可以调用这个函数,而不是从相同原型继承的任何其他对象都可以):
myObj.doSomethingNew = doSomething; /*想到了关联这个词,不知道合适的不~*/
myObj.doSomethingNew(x,y,z);
补充:如果希望类的每一个实例都能访问添加的一个特定函数:在构造函数中将函数(预先定义的或者以内嵌方式声明的)添加到新的对象上,或者将此函数附加到原型上。
其实此时,函数仍然不是非常牢固地附加在对象上,这里的意思是一个其他的对象可以借用这个附加在特定对象上的函数。
那下面就来仔细看看从其他对象借用函数
从其他对象借用函数
一个对象可以借用另外一个对象的函数,并且通过自身来调用它。
树:
function Tree (name, leaf, bark)
{
this.name = name;
this.leaf = leaf;
this.bark = bark;
}
Tree.prototype.describe = function()
{
return this.name + “: leaf = “ + this.leaf +” , bark =” + this.bark;
}
注:对于prototype不在阐述了,这个不知道的话可以看下前几篇关于原型的介绍。
Tree实例化:
var Beech = new Tree(“Beech”, “green, serrated edge”, “smooth”);
alert(Beech.describe());
注:警告框将显示文本:Beech:leaf = green, serrated edge, bark = smooth。
接下来
狗:
function Dog(name,bark)
{
this.name = name;
this.bark = bark;
}
狗实例化:
var Snowy = new Dog(“Snowy”, “wau! wau!”);
好吧重点到了哦,Snowy可以劫持Tree类的函数:
var tmpFunc = Beech.describe;
tmpFunc.call(Snowy);
这里就要充分理解call函数了,function.call()的第一个参数是上下文对象,即特殊变量this将被确定为的对象。那么你就可以认为第二行代码就相当于执行:Snowy.tmpFunc()。可以想象如果没有Snowy,默认就是this对象,而这时this对象便是Beech对象。那么describe()中的this便随之对应改变(个人理解,只做参考,如有错误请指出)
狗调用了实际上属于数的函数!!怎么发生的?
答案是函数并不属于那棵树。尽管其中插入了this引用,将函数付给Tree原型形成的绑定仅仅是因为这样能够使用更短的符号MyTree.describe()来调用它。在内部实现中,函数保存为一段每次调用时就会求值的文本,因此this的含义在一次调用和下一次调用中并不相同。
好了关于函数就介绍到这里了,下一篇中将回到Ajax,介绍Ajax事件处理和函数上下文
函数是一等公民
函数有点像Java的方法,调用时,也有参数和返回值。但是有一个关键的区别:Java方法天生捆绑在定义它的类上,不能与类脱离开存在;JavaScript函数是自由浮动的实体,自身就可以作为正常等对象(静态的Java方法位于这两者之间——它们并没有捆绑在任何对象实例上,但是仍然捆绑在类的定义上)。
在JavaScript中,Function是一个内建的对象类型。就像期待的那样,它包含可执行的代码,可以调用,但是它也是Object类的子孙,并且可以做JavaScript对象可以做的任何事情,例如使用名称来保存属性。Function对象上很可能(并且非常普遍)附加其他的Function对象作为它的方法。
在单独一行中引用一个函数并且调用它,例如:
var result = MyObject.doSomething(x,y,z)
然而,Function是第一等的对象,它也可以通过call()方法(以及它的近亲apply()方法)来执行:
var result = MyObject.doSomething.call(MyOtherObject,x,y,z)
/*相当于MyObject.doSomething(x,y,z)*/
或者甚至是:
var result = MyObject[‘doSomething’].call(MyOtherObject,x,y,z)
注:Function.call()的第一个参数是在调用期间作为函数上下文使用的对象,随后的参数作为函数调用的参数。apply()的工作方式略微不同,其中第二个参数是一个传递给函数调用的参数数组,允许以编程方式调用那些参数列表长度不确定的函数,这带来了巨大的灵活性。
补充:call()方法来实现继承:
function Class10()
{
……
}
function Class11()
{
……
}
function Class2()
{
Class10.call(this);
Class11.call(this);
}
这样Class2便实现了多重继承,对于call的介绍可上网进一步查看。
JavaScript函数的参数列表的长度不固定。使用比声明更多或者更少的参数来调用一个Java或者C#方法将会产生编译期错误。而JavaScript仅仅忽略任何额外的参数,并且给缺少的参数赋值undefined。一个特别智能的函数可以通过arguments属性查询它自己的参数列表,比起为缺少的值分配明智的默认值,抛出一个异常或者采取任何其他的补救措施。这个特征可以通过将获取和设置方法组合在单个函数中来演示,例如:
function area(value)
{
if(value)
{
this.area = value;
}
return this.area;
}
注:如果简单地调用area(),那么value是未定义的,所以没有发生赋值,函数作为getter方法来使用。如果传入了一个值,函数就作为setter方法来使用。这种技术被Mike Foster的x库广泛使用,所以,如果你计划使用这个库,你很快就会熟悉这个习惯用法。
当我们对函数作为第一等对象的独立性加以利用时,它才变得真正有趣起来。
面向对象附加函数
作为一种函数式语言,JavaScript允许脱离任何对象来定义函数,例如:
function doSomething(x,y,z) {……}
还可以使用内嵌的方式来定义:
var doSomething = function(x,y,z) {……}
函数可以附加到对象上,我们可以将预先定义的函数附加到预先定义的对象上(在这种情况下,只有该对象可以调用这个函数,而不是从相同原型继承的任何其他对象都可以):
myObj.doSomethingNew = doSomething; /*想到了关联这个词,不知道合适的不~*/
myObj.doSomethingNew(x,y,z);
补充:如果希望类的每一个实例都能访问添加的一个特定函数:在构造函数中将函数(预先定义的或者以内嵌方式声明的)添加到新的对象上,或者将此函数附加到原型上。
其实此时,函数仍然不是非常牢固地附加在对象上,这里的意思是一个其他的对象可以借用这个附加在特定对象上的函数。
那下面就来仔细看看从其他对象借用函数
从其他对象借用函数
一个对象可以借用另外一个对象的函数,并且通过自身来调用它。
树:
function Tree (name, leaf, bark)
{
this.name = name;
this.leaf = leaf;
this.bark = bark;
}
Tree.prototype.describe = function()
{
return this.name + “: leaf = “ + this.leaf +” , bark =” + this.bark;
}
注:对于prototype不在阐述了,这个不知道的话可以看下前几篇关于原型的介绍。
Tree实例化:
var Beech = new Tree(“Beech”, “green, serrated edge”, “smooth”);
alert(Beech.describe());
注:警告框将显示文本:Beech:leaf = green, serrated edge, bark = smooth。
接下来
狗:
function Dog(name,bark)
{
this.name = name;
this.bark = bark;
}
狗实例化:
var Snowy = new Dog(“Snowy”, “wau! wau!”);
好吧重点到了哦,Snowy可以劫持Tree类的函数:
var tmpFunc = Beech.describe;
tmpFunc.call(Snowy);
这里就要充分理解call函数了,function.call()的第一个参数是上下文对象,即特殊变量this将被确定为的对象。那么你就可以认为第二行代码就相当于执行:Snowy.tmpFunc()。可以想象如果没有Snowy,默认就是this对象,而这时this对象便是Beech对象。那么describe()中的this便随之对应改变(个人理解,只做参考,如有错误请指出)
狗调用了实际上属于数的函数!!怎么发生的?
答案是函数并不属于那棵树。尽管其中插入了this引用,将函数付给Tree原型形成的绑定仅仅是因为这样能够使用更短的符号MyTree.describe()来调用它。在内部实现中,函数保存为一段每次调用时就会求值的文本,因此this的含义在一次调用和下一次调用中并不相同。
好了关于函数就介绍到这里了,下一篇中将回到Ajax,介绍Ajax事件处理和函数上下文