构造函数:用于创建特定类型的对象——不仅声明了使用的对象,构造函数还
可以接受参数以便第一次创建对象的时候设置对象的成员值。
构造函数是实现实例的,可多次实例化,每一次的new都是一次的全部代码执行
一般特点:
- 函数首字母大写,区别于其他函数,
function Person(){}
- 函数内部的this指向new实例化的新对象
var o = new Person()
;
Person内部的this指向o - 多次new,存在内存消耗问题(重复new)
1.基本的构造函数
function Person(name,book) {
this.name = name;
this.book = book;
this.output = function(){
return this.name+' read '+this.book;
}
}
var may = new Person('may','The little prince'); //this指向may
console.log(may.name); //may
console.log(may.output()); //may read The little prince
console.log(may instanceof Person); //true,may是Person的一个实例
存在一些问题:多次实例化,就会多次执行函数output();会大量消耗内存,所以下一步降低内存消耗。
2.解决内存消耗的问题,提出function
方案一:提出output到构造函数外部
function Person(name,book) {
this.name = name;
this.book = book;
this.output = read;
}
function read() { //单独提出,用的时候再执行
return this.name+' read '+this.book;
}
var alice = new Person('alice','gone with the wind')
console.log(alice.output());
方案二:利用原型链(推荐)
调用构造函数创建对象的时候,构造函数原型的属性都可以在
新创建的对象上使用,多个Person对象实例都可以共享使用output(),共享使用
function Person(name,book) {
this.name = name;
this.book = book;
}
Person.prototype.output = function () {
return this.name+' read '+this.book;
}
var alice = new Person('alice','gone with the wind')
console.log(alice.output());
3.用new和不用new的区别
不用new会有什么问题?
function Person(name,book) {
this.name = name;
this.book = book;
this.output = function(){
return this.name+' read '+this.book;
}
}
/*不用new,则作为函数调用*/
Person('alice','The little prince'); //this指向window
console.log(window.name); //alice
console.log(window.output()); //alice read The little prince
var alice = Person('alice','The little prince'); //this指向window
console.log(typeof alice); //undefined
console.log(alice.name); //error
console.log(alice.output()); //error
不用new的,不报错的解决方式
利用新对象,在新对象的作用域上使用
function Person(name,book) {
this.name = name;
this.book = book;
this.output = function(){
return this.name+' read '+this.book;
}
}
var may = new Object();
Person.call(may,'may','The little prince'); //利用call,使的this指向may
console.log(may.name); //may
console.log(may.output()); //may read The little prince
默认,强制使用new的实现方式
function Person(name,book) {
//判断this是否是Person的实例,没有则实例化
if(!(this instanceof Person)){
return new Person(name,book);
}
/*公有*/
this.name = name;
this.book = book;
this.output = function(){
return this.name+' read '+this.book;
}
}
var may = Person('may','The little prince'); //this指向may
console.log(may.name); //may
console.log(may.output()); //may read The little prince
4.复杂构造函数,测试与总结(完全版)
包含,公有及私有属相及方法,以及原型的使用
function Person(weight,age) {
/*公有*/
this.weight = weight;
this.sayWeight = function(){ //每次实例化后都要重新构造
console.log("It's "+this.weight);
}
/*私有*/
var age = '18';
var getAge = function () {
cosnoel.log(age);
}
}
Person.prototype.hello = 'hello world!';
Person.prototype.sayHello = function(){
console.log('hello everybody!');
}
/*静态属性及方法*/
Person.address = 'china';
Person.sayAddress = function () {
console.log(this.address);
}
var alice = new Person('50kg','10');
/******************测试,类属性*******************/
// console.log(alice.weight); //50kg
// console.log(alice.age); //undefined,私有,不被实例化
// console.log(alice.hello); //hello world!,原型上的属性,被所有实例继承
// console.log(alice.address); //undefined,address属于函数本身的属性,
// //也可以说,是类属性和类本身(即函数本身)相关,和类实例没有关系
// console.log(alice.constructor.address); //china,通过函数的实例来访问函数的属性,
// // 则需要先访问该实例的构造函数,进而访问该函数的属性
// console.log(Person.weight); //undefined,this指向的是实例化的对象alice,不是Person
// console.log(Person.age); //undefined,私有,不被实例化对象拥有,也不被方法本身的Person对象拥有
// console.log(Person.hello); //undefined,错误调用,在原型上呢
// console.log(Person.address); //china,类自身的方法
/******************测试,类方法(解释同属性)*******************/
// alice.sayName(); //It's alice
// alice.getAge(); //FF:...not a function,私有,不被实例化
// alice.sayHello(); //hello everybody!,原型上的方法都会被实例继承
// alice.sayAddress(); //FF:...not a function,类本身的方法,不被实例化的对象继承
// alice.constructor.sayAddress(); //china.用constructor访问this指向调用的对象,这里应该是Person
// Person.sayName(); //undefined,
// Person.getAge(); //undefined,
// Person.sayHello(); //undefined,
// Person.sayAddress(); //china,
/******************测试,prototype*******************/
// console.log(alice.prototype);/*undefined,实例对象没有prototype*/
// console.log(Person.prototype);/*Object,*/
// Person.prototype.sayHello();/*hello everybody!,*/
// console.log(Person.prototype.hello);/*hello world!,*/
// console.log(Person.prototype.constructor);/*返回构造函数Person(){},*/
// console.log(Person.prototype.constructor.address);/*china,*/
// console.log(Person.prototype.constructor.name);/*Person,构造函数的名称*/
//小结:实例化的对象没有prototype属性,只有构造函数才有(即构造函数保存了对prototype属性的引用)
参考文章:
http://www.cnblogs.com/jikey/archive/2011/05/13/2045005.html
http://www.cnblogs.com/mrsunny/archive/2011/05/09/2041185.html
http://www.cnblogs.com/TomXu/archive/2012/02/21/2352994.html