// arguments.callee的用法(在严格模式下会出错)
// 实现阶乘
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1); //引用该函数的函数体内当前正在执行的函数
}
}
一、创建对象
// 工厂模式创造对象
// 缺点:没有解决对象识别的问题,即如何知道一个对象的类型
function createPerson(name,age,job) {
var o = new Object();
o.name=name;
o.age=age;
o.job=job;
o.sayName=function () {
alert(this.name);
}
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
// 构造函数模式创建对象(任何函数,只要通过 new 操作符来调用,那它就可以作为构造函数)
// 缺点:每次实例化,都会重建其方法,所有对象实例不能共享它所包含的属性和方法
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
// 构造函数名首字母大写
// 要创建构造函数的新实例,必须使用 new 操作符。
// 原型模式创建对象
// 可以让所有对象实例共享它所包含的属性和方法
function Person(){} // 此时constructor属性指向Person函数
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
// 更简单的原型语法,此时constructor属性指向Object构造函数,而不是Person函数,所以通过constructor无法确定对象的类型
function Person(){}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
var friend=new Person();
friend.constructor==Person; // false,可以在定义时设置,constructor : Person,
friend.constructor==Object; // true
// 结合构造函数和原型(最好)
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
二、原型链
// 每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true
// 在通过原型链实现继承时,不能使用对象字面量创建原型方法。因为这样做就会重写原型链,如下面的例子所示。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//继承了 SuperType
SubType.prototype = new SuperType();
// 使用字面量添加新方法,会导致上一行代码无效
SubType.prototype = {
getSubValue : function (){
return this.subproperty;
},
someOtherMethod : function (){
return false;
}
};
var instance = new SubType();
alert(instance.getSuperValue()); // error!