本文之所以单独拿函数来讲解,是因为JavaScript函数有其独特之处。
1. javascript函数默认没有重载
我们可以看到函数即使没有定义参数,调用时传递参数仍然可以传递参数,参数被argument对象接收
function sayHi() {
console.log(arguments.length);
if (arguments[0] == "bye") {
return;
}
console.log("arguments[0]="+arguments[0]);
}
sayHi("hello");
console.log("sayHi instanceof Function="+(sayHi instanceof Function)); //true
console.log("sayHi instanceof Object="+(sayHi instanceof Object)); //true
//说明函数基类是Object
console.log("Function instanceof Object="+(Function instanceof Object));//true
2. 闭包: 词法表示包含不被计算的变量(变量不在函数内计算)的函数
2.1 这就是一个简单的闭包
var sMessage="hello world";
function sayHello() {
console.log(sMessage);
}
sayHello(); // ''hello world''
2.2 在函数中定义一个闭包(也就是说函数中定义函数)
var iBaseNum=10;
//函数不return数据默认返回undefined
function addNum(iNum1,iNum2) {
function doAdd() {
return iNum1+iNum2+iBaseNum;
}
return doAdd;
}
console.log("addNum(10,10)="+addNum(10,10)());
3. ECMAScript不仅可以创建对像,修改已有对象的行为。
通过prototype属性,可以改变和添加构造函数的属性和方法,这点已经在原型继承那篇文章已经在使用
3.1 创建新方法
3.1.1 通过对象已有方法创建新方法
我们知道Number类型toString方法很容易讲数据转为各种进制,使用时传入进制,即可转换。
var num=new Number(10);
console.log(num.toString(16)); //10转为16进制a
我们换一种直观写法
Number.prototype.toHexString=function () {
return this.toString(16)
}
console.log("num.toHexString()="+num.toHexString());
3.1.2 重命名已有方法,不改变原来方法效果
Array.prototype.enqueue=function (item) {
this.push(item);
}
Array.prototype.dequeue=function () {
this.shift();
}
var arr=new Array(3);
arr[0]="George";
arr[1]="John";
arr[2]="Thomas";
arr.enqueue("Bill");
console.log("arr="+arr);
arr.dequeue();
console.log("arr="+arr);
3.1.3 添加与已有方法无关的方法
// ES5开始提供了indexOf方法
Array.prototype.indexOf=function (item) {
for(var i=0;i
3.1.4 为本地对象添加新方法
//要给每个本地对象都添加上新方法,必须定义在Object的prototype属性上。
Object.prototype.showValue=function () {
console.log(this.valueOf());
};
var str="hello";
var iNum=25;
str.showValue();
iNum.showValue();
console.log(Object.prototype.constructor); //Object() { [native code] }
console.log(Object.constructor); // Function() { [native code] }
var num= new Number(10);
console.log(Number.prototype.constructor); // Number() { [native code] }
console.log(Object.constructor); //Function() { [native code] }
3.2 重新定义已有方法
//函数名只是指向函数的指针,可轻松修改指针指向其它函数
function sayHi() {
console.log("hi");
}
// Function 的 toString() 方法通常输出的是函数的源代码
console.log(sayHi.toString()); //function sayHi() {console.log("hi");}
//重新定义已有方法
Function.prototype.toString=function () {
return "Function code hidden";
}
//改变后
console.log(sayHi.toString()); //Function code hidden
问题:toString指向的原始函数函数会被销毁,由于以后你可能还会用到。
所以最稳妥的做法是再覆盖原始方法之前报这个函数指针存起来
使用前用originalToString存储原始的toString指针(函数名就是指向函数的指针)
Function.prototype.originalToString=Function.prototype.toString;
// 新toString方法,函数判断函数源码长度是否大于100
Function.prototype.toString=function () {
if(this.originalToString().length>100){
return "Function too long to display.";
}else {
return this.originalToString();
}
}
4. 极晚绑定(very late binding)(对象定义完后,才绑定方法和属性)
其实这点已经在前面文章讲到过,还是简单说一下
var obj=new Object();
Object.prototype.sayHi=function () {
console.log("我是极晚绑定的sayHi")
}
Object.prototype.name="我是极晚绑定的属性";
obj.sayHi(); //我是极晚绑定的sayHi
console.log(obj.name); //我是极晚绑定的属性
对象在已经创建完毕后,再给对象绑定方法和属性能立即在前面已创建对象上使用