类、构造函数、原型
构造函数
new
操作符用来生成一个新的对象,
new
后面必须要跟上一个函数,也就是我们常说的构造函数,构造函数的工作原理又是怎样的呢?
先看一个例子:
JS
代码:
(
见附件
test1.html)
function Person(name,sex){
this.name = name;
this.sex = sex;
}
var per = new Person("wangsy","male");
alert("name:" + per.name + "_sex:" + per.sex);
下面说明一下这个工作的步骤:
开始创建了一个函数
(
不是方法,只是一个普通的函数
),
注意用到了
this
关键字,也就是说通过对象调用
”
方法
”
的时候,
this
关键字会指向该对象
(
不使用对象直接调用该函数则
this
指向整个的
script
域,或者函数所在的域
)
。当我们使用
new
操作符时,
js
会先创建一个空的对象,然后这个对象被
new
后面的方法的
this
关键字引用!确定如果的方法中通过操作
this
就给这个新创建的对象相应的赋予了属性,最后返回这个经过处理的对象。这样上面的例子就很清楚:先创建一个空对象,然后调用
person
方法对其进行赋值,最后返回该对象,我们就得到了一个
per
对象。
在
js
中,每个对象都有一个
prototype
属性,这个属性指向了一个
prototype
对象。
上面我们提到了用
new
来创建一个对象的过程,事实上在这个过程中,当创建了空对象后,
new
会接着操作刚生成的这个对象的
prototype
属性。
每个方法都有一个
prototype
属性
(
因为方法本身也是对象
)
,
new
操作符生成的新对象的
prototype
属性值和构造方法的
prototype
属性值是一致的。构造方法的
prototype
属性指向了一个
prototype
对象,这个
prototype
对象初始只有一个属性
constructor,
而这个
constructor
属性又指向了
prototype
属性所在的方法。
这样,当用构造函数创建一个新的对象时,它会获取构造函数的
prototype
属性所指向的
prototype
对象的所有属性,对构造函数对应的
prototype
对象所做的任何操作都会反应到它所生成的对象身上,所有的这些对象共享构造函数对应的
prototype
对象的属性
(
包括方法
)
。具体例子:
JS
代码:
(
见附件
test2.html)
//
构造函数
function Person(name,sex){
this.name = name;
this.sex = sex;
}
//
为
prototype
属性对应的
prototype
对象的属性赋值
Person.prototype.age = 12;
//
添加方法
Person.prototype.print = function(){
alert(this.name + "_" + this.sex + "_" + this.age);
}
var p1 = new Person("name1","male");
var p2 = new Person("name2","male");
//name1_male_12
p1.print();
//name2_male_12
p2.print();
//
改变
prototype
对象的属性值,注意是操作构造函数的
prototype
属性
Person.prototype.age = 18;
//name1_male_18
p1.print();
//name2_male_18
p2.print();
改变对象的
prototype
属性和
prototype
属性的注意事项:给出一种不是很恰当的解释,或许有助于我们理解,当我们
new
了一个对象之后,这个对象就会获得构造函数的
prototype
属性
(
包括函数和变量
)
,可以认为是构造函数
(
类
)
继承了它的
prototype
属性对应的
prototype
对象的函数和变量,也就是说,
prototype
对象模拟了一个超类的效果,听着比较拗口,看个实例:
JS
代码:
(
见附件
test3.html)
//Person
类的构造函数
function Person(name,sex){
this.name = name;
this.sex = name;
}
//
为
Person
类的
prototype
属性对应的
prototype
对象的属性赋值
//
相当于为
Person
类的父类添加属性
//
为
Person
类的父类添加方法
Person.prototype.print = function(){
alert(this.name + "_" + this.sex + "_" + this.age);
}
//p1
的
age
属性继承了
Person
类的父类
(
即
prototype
对象
)
var p1 = new Person("name1","male");
var p2 = new Person("name2","male");
//name1_male_12
p1.print();
//name2_male_12
p2.print();
//
改变
p1
实例的
age
属
p1.age = 34;
//name1_male_34
p1.print();
//name2_male_12
p2.print();
//
改变
Person
类的超类的
age
属性
Person.prototype.age = 22;
//p1
的
age
属性并没有随着
prototype
属性的改变而改变
p1.print();
//p2
的属性发生了变化
p2.print();
//
改变
p1
对象的
print
方法
p1.print = function(){
alert("I am p1");
}
//p1
的方法发生了改变
p1.print();
//p2
的方法并没有改变
p2.print();
//
改变
Person
超类的
print
方法
Person.prototype.print = function(){
alert("new print method");
}
//p1
的
print
方法仍旧是自己的方法
p1.print();
//p2
的
print
方法随着超类方法的改变而改变
p2.print();
转载于:https://blog.51cto.com/jawsy/166325