1.使用function声明方法和类型
可以使用function声明一个方法,比如:
function testMethod() {
alert("Hello world");
}
testMethod(); //输出"Hello world!"
除了方法,function还可以用来声明"类型"。JavaScript中本没有"类型"的概念,也就是Class的概念,但可以使用function伪装一个类型。
function Car()
{
this.color = "none";
if(typeof Car._initialized =="undefined")
{
Car.prototype.showColor=function(){
alert(this.color);
}
}
Car._initialized =true;
};
上面的代码声明了一个Car类,并且带有一个color属性和一个showColor()方法。这里使用的是“动态原型”方法。
现在使用"new"运算符创建一个类的实例
var car=new Car();
car.showColor(); //输出 “none”
color.color= "blue";
car.showColor(); //输出 “blue”
2.function 的本质
function的本质很简单。function变量是引用类型,内容存储的是指向function内容的指针,function的内容就是函数体。
JavaScript中的对象有一个特点,里面存储的都是name/value。一个属性的名称就是name,属性的值就是value,
但JavaScript中的function也是一个name/value,可以使用alert()方法输出function变量的内容:
3.new 运算符
function类型的对象配合new运算法,可以创建一个实例。
var car = new Car();
首字母大写的Car是一个函数,但是使用new运算符生成的是一个object:
alert(typeof car); //output object
而Car函数本身则更像是一个类的构造函数。实际上,new与运算符的操作等价于下面的语句。
var car2 = { };//建议几个空对象
//将car2的原型设置为Car.prototype.这一步是通过JavaScript内部的Object.create实现的,但是此函数使内部函数无法直接访问
Car.call(car2); //修改函数调用的上下文
alert(car2.color);
4.function中的arguments参数对象
JS不支持方法的重载,原因是在JS中同名的function只能有一个,并且function()函数的参数个数可以使任意的
虽然无法支持“重载”,但可以通过arguments对象伪装重载,让一个函数根据不同的参数实现不同的功能
arguments是在function中的特殊对象,通过arguments对象可以访问到function调用者传递的所有参数对象,比如获取到传入的参数个数:
function testMethod()
{
alert(arguments.length);
}
testMethod(); //output 0;
testMethod("abc"); //output 1
可以通过arguments的索引arguments[index]获取每一个传入的参数值:
function myMethod()
{
alert(arguments instanceof Array);
if(arguments.lenght == 0)
{
alert("no arguments");
}
else if(arguments.lenght == 1)
{
alert("Hello:" + arguments[0].toString())
}
}
myMethod();
myMethod("ziqiu.zhang");
上面的方法通过判断参数的个数实现了伪装重载。但这种实现并不好,因为所有的重载逻辑都集中在一个方法中,并且有令人厌烦的多个if-else分支
但是使用arguments可以开发出功能强大,灵活的函数。在开发jQuery的插件时就要经常使用arguments对象实现函数的伪重载。
5.this指针
Js的this是函数上下文,不是在声明时决定的,而是在调用时决定的。因为全局函数其实就是window的属性,所以在顶层调用全局函数时的this是指Window对象
<script type="text/JavaScript">
var oName={name:"ziqiu.zhang"};
window.name="I am window";
//showName是一个函数,用来显示对象的name属性
function showName()
{
alert(this.name);
}
oName.show = showName;
window.show=showName;
showName(); //输出为"I am window"
oName.show(); //输出为"ziqiu.zhang";
window.show(); //输出为"I am window"
</script>
showName是一个function,使用alert语句输出this.Name. 因为showName是一个全局的函数,所以其实showName是window的一个属性window.showName,调用全局的showName
就是调用window.showName,因为Window上的name属性为“I am window”,所以直接调用showName和调用window.showName都会输出"I am window".
oName是一个对象,前面已经讲过函数也是一个属性,可以像属性一样赋值,所以将shoeName()方法复制给oName的show()方法。当调用oName.show()方法时,也会出发alert(this.name)
语句,但是此时方法的调用者是oName,所以this.name输出的是oName的name属性。
利用"this指向函数调用者"的特性,可以实现链式调用。jQuery中大部分都是链式调用。
var oName = {
name:"ziqiu.zhang", age:99
}
oName.showName = function()
{
alert(this.name);
return this;
};
oName.showAge = function()
{
alert(this.age);
return this;
};
oName.showName().showAge();
使用链式调用的关键点就是要返回调用者本身,也就是this指针。
在使用this时,也常常因为this指向函数上下文的特性,导致引用的错误
var myClass=
{
checkName:function() {return true;},
test:function(){
if(this.checkName()){
alert("ZZQ");
}
}
}
$("#btnTest").click(myClass.test);
上面的例子中试图使用面向对象的方式,将一些方法封装在myClass中,并为btnTest对象添加单击事件的事件处理函数。现在如果单击btnTest调用myClass.test()方法,会发生错误,提示找不到checkName() 方法。
jQuery.proxy函数可以解决此问题。