您的位置:首页 > Web前端 > JavaScript

javascript构造函数

2016-01-07 21:24 681 查看
//构造函数
//使自己的对象多次复制,同时实例根据设置的访问等级可以访问其内部的属性和方法
//当对象被实例化后,构造函数会立即执行它所包含的任何代码
function myObject(msg){
//特权属性(公有属性)
this.myMsg = msg; //只在被实例化后的实例中可调用
this.address = '上海';

//私有属性
var name = '豪情';
var age = 29;
var that = this;

//私有方法
function sayName(){
alert(that.name);
}
//特权方法(公有方法)
//能被外部公开访问
//这个方法每次实例化都要重新构造而prototype是原型共享,所有实例化后,都共同引用同一个
this.sayAge = function(){
alert(name); //在公有方法中可以访问私有成员
}
//私有和特权成员在函数的内部,在构造函数创建的每个实例中都会包含同样的私有和特权成员的副本,
//因而实例越多占用的内存越多
}
//公有方法
//适用于通过new关键字实例化的该对象的每个实例
//向prototype中添加成员将会把新方法添加到构造函数的底层中去
myObject.prototype.sayHello = function(){
alert('hello everyone!');
}
//静态属性
//适用于对象的特殊实例,就是作为Function对象实例的构造函数本身
myObject.name = 'china';
//静态方法
myObject.alertname = function(){
alert(this.name);
}
//实例化
var m1 = new myObject('111');
//---- 测试属性 ----//
//console.log(myObject.name); //china
//console.log(m1.name); //undefined, 静态属性不适用于一般实例
//console.log(m1.constructor.name); //china, 想访问类的静态属性,先访问该实例的构造函数,然后在访问该类静态属性
//console.log(myObject.address); //undefined, myObject中的this指的不是函数本身,而是调用address的对象,而且只能是对象
//console.log(m1.address); //上海 此时this指的是实例化后的m1

//---- 测试方法 ----//
//myObject.alertname(); //china,直接调用函数的类方法
//m1.alertname(); //FF: m1.alertname is not a function, alertname 是myObject类的方法,和实例对象没有直接关系
//m1.constructor.alertname(); //china, 调用该对象构造函数(类函数)的方法(函数)
//m1.sayHello(); //hello everyone, myObject类的prototype原型下的方法将会被实例继承
//myObject.sayHello(); //myObject.sayHello is not a function,sayHello是原型方法,不是类的方法

//---- 测试prototype ----//
//console.log(m1.prototype); //undefined, 实例对象没有prototype
//console.log(myObject.prototype); //Object
//alert(myObject.prototype.constructor); //console.log返回myObject(msg),此时alert()更清楚,相当于myObject
//console.log(myObject.prototype.constructor.name); //china, 相当于myObject.name;
//myObject.prototype={}重写之后,构造函数myObject的原型对象的constructor属性不再指向myObject了,因为该语法的本质是完全重写了默认的原型对象,所以constructor属性也就变成了新对象的constructor属性,指向Object构造函数,我们此时就不能通过constuctor来确定对象的类型了。可以通过myObject.prototype.constructor =myObject恢复constructor的指针。


<script>
function Circle( radius ){
this.r = radius;
this.des = "圆形";

this.showInfo = function(){
alert("这是一个"+this.des);
}
}

function Circle_area(r){ return Circle.PI*this.r*this.r; }

function Circle_perimeter(r){ return  2*Circle.PI*r;}

Circle.PI = 3.14;
Circle.perimeter = Circle_perimeter;
Circle.prototype.area = Circle_area;

var c = new Circle(3);

//测试类属性
//alert(Circle.PI )//3.14
//alert(c.PI)//undefined 因为类属性是和类本身,也就是函数本身相关联的,和类实例没有直接关系。
//alert(c.constructor.PI)//3.14 如果想通过类实例访问类属性,那么就需要先访问该实例的构造函数,进而访问该类属性
//alert(Circle.des)//undefined 因为函数Circle函数中的this.des中的this指代的不是函数本身,而是调用r的对象,而且只能是对象。
//alert(c.des)//圆形 this此时为实例化的 对象c。

/*结论:
面向对象的角度:类属性是类对象的直接属性,且该属性与基于该类对象生成的实例对象没有直接关系,无法直接调用。
可以直接通过 类名.属性名 调用该类属性。如果想通过该类对象的实例对象调用类属性,那么可以使用 对象实例.constructor属性
调用该对象的类对象,然后通过类对象调用其类属性
javascript函数角度:类属性是javascript函数对象的直接属性变量(这里之所以称之为属性变量是由于javascript变量和属性的同一
性),且该属性变量与基于该函数对象构造出来的对象引用(生成了一个对象,这个对象实际上是一个空对象,并且保存了对构造
函数以及构造函数初始化时函数内部this关键字下的相关属性和函数的引用[c.prototype和构造函数中this.下面的相关属性、函数]:)
没有直接关系,如果想通过基于构造函数生成的对象c调用构造函数对象的属性变量PI,那么需要通过c.constructor属性找到该构造
函数对象,并通过该对象获取其属性变量。
*/

//测试类方法
//alert(Circle.perimeter(3)); //18.4 直接调用函数的类方法。
//alert( c.perimeter(3) ); //FF:c.perimeter is not a function IE:对象或属性不支持此方法。因为perimeter函数是Circle类的类方法,和实例对象没有直接关系
//alert(c.constructor.perimeter(3));//18.84 调用该对象构造函数(类函数)的方法(函数)。
//alert(c.area(3))//28.25.... Circle类的prototype原型属性下的area方法将会被Circle类的实例对象继承。
//alert(Circle.area(3));//FF: 错误: Circle.area is not a function  因为area方法是Circle类的原型属性的方法,并不是Circle类的直接方法。

//结论:同上,把属性换成了方法,把属性变量换成了函数。

//测试prototype对象属性
//alert(c.prototype); //undefined 实例对象没有ptototype属性
//alert(Circle.prototype); //object Object
//alert(Circle.prototype.constructor)//返回Circle的函数体(函数代码体),相当于alert(Circle)
//alert(Circle.prototype.area(3));//NaN 方法调用成功,但是返回结果却是NaN,原因是area函数内部的this.r是undefined。
//alert(Circle.prototype.PI) //undefined因为PI属性是Circle类函数的直接属性,并不会在prototype属性下存在
//alert(Circle.prototype.constructor.PI)//3.14 通过Circle类的原型对象调用该原型对象的构造函数(类函数),再通过类函数调用PI属性。

/*结论:prototype原型对象是javascript基于原型链表实现的一个重要属性。
Javascript角度:1. 实例对象没有prototype属性,只有构造函数才有prototype属性,也就是说构造函数本身保存了对prototype属性
的引用。。2. prototype属性对象有一个constructor属性,保存了引用他自己的构造函数的引用(看起来像是个循环:A指向B,B指向A...)
3.prototype对象(不要被我这里的属性对象,对象,对象属性搞晕乎了,说是属性对象,就是说当前这个东西他首先是某个对象的属性,
同时自己也是个对象。对象属性就是说它是某个对象的属性。)的属性变量和属性对象将会被该prototype对象引用的构造函数所创建的
对象继承(function A(){} A.prototype.pa = function(){} var oA = new A(); 那么oA将会继承属性函数pa)。
*/

/*这里对 对象属性,对象方法不再做详细测试。
1.javascript对象实例的在通过其构造函数进行实例化的过程中,保存了对构造函数中所有this关键字引用的属性和方法的引用(这里不
讨论对象直接量语法的情况)。但如果构造函数中没有通过this指定,对象实例将无法调用该方法。2.javascript可以通过构造函数创建
多个实例,实例会通过__proto__属性继承原型对象的属性和方法。如果对实例对象的属性和方法进行读写操作,不会影响其原型对象的
属性和方法,也就是说,对于原型对象,javascript实例对象只能读,不能写。那当我们对实例对象的属性和方法进行修改的时候也可以
改变其值这是为什么呢?其实当我们试图在实例对象中使用继承自原型对象的属性或方法的时候,javascript会在我们的实例对象中复
制一个属性或方法的副本,这样,我们操作的时候,其实操作的就是实例对象自己的属性或方法了。

*/
//测试__proto__属性
//alert(c.__proto__)//FF:object IE8:undefined 该属性指向Circle.prototype,也就是说调用该对象将会返回Circle的prototype属性。
//由于IE8及以下版本不支持__proto__属性,所以以下结果都在FF下得出。
//alert(c.__proto__.PI)//undefined 因为函数原型下面没有PI属性,PI是类函数Circle的直接属性
//alert(c.__proto__.area(3))//NaN 该函数执行成功,返回值为NaN是由于函数体中的this.r为undefined。

/*结论:__proto__属性保存了对创建该对象的构造函数引用prototype属性的引用,也就是说构造函数可以引用prototype,基于该构
造函数生成的实例也可以引用,只不过引用的方式不一样。*/
</script>


参考:
http://www.cnblogs.com/jikey/archive/2011/05/13/2045005.html http://www.cnblogs.com/mrsunny/archive/2011/05/09/2041185.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: