类的创建
在JavaScript里面,函数即时函数,也是方法,也是一个类等等,面向对象语言里,类的定义都是使用new关键字来定义类的,利用他来调用构造器,但是JavaScript确没有那么严格,这里函数就是类,所以用函数创建对象,返回的对象就是该类的实例
利用new创建
<script type="text/javascript">
// 定义简单函数
function Person(name)
{
this.name = name;
function a()
{
//函数体
}
}
// 使用new关键字,简单创建Person类的实例
var p = new Person('aile');
// 如果p是Person实例,则输出静态文本
if (p instanceof Person)
document.writeln("p是Person的实例<br />");
// 如果p是Object 实例,则输出静态文本
if(p instanceof Object)
document.writeln("p是Object的实例");
</script>
在定义Person函数的同时,也相当于定义了一个Person的类,所以即是Person的实例,也是Object类的实例,里面的this.name=name,就相当于类的构造器,而 function就相当于类的方法
利用Object创建
var obj = new Object(); //创建空对象
然后动态的加属性或者方法(Java、C、C++等高级语言却没有这么方便)
<script type="text/javascript">
var obj = new Object();
obj.name = "aile";
obj.age = 23;
//这样就相当于给对象增加了属性
obj.info = function()
{
alert("姓名:" + this.name + ",年龄:" + this.age);
}
//这样就相当于给对象增加了方法
</script>
使用JSON语法创建对象
JSON(JavaScript Object Notation)可以不用new直接创建对象,使用花括号,然后将对象写成“key:value”的形式(和Java里面的Map有点像,前面是索引,后面是值,可以按索引找值)
<script type = "text/javascript">
var per = {
name : "aile",
age : 23
}
</script>
用花括号括起来,属性名与属性值之间用“:”隔开,每个对象之间用“,”隔开,但最后一个属性后面不能有“,”
JSON语法里面的属性值,不只可以是基本类型和字符串,也可以者函数或者数组等
<script type = "text/javascript">
var per = {
name : "aile",
age : 23,
p : {
name : "aimeng",
age : "14"
}
info : function(){
alert("姓名:" + this.name + ",年龄:" + this.age);
}
}
</script>
类的继承
JavaScript没有真正意义上面向对象语言的继承,因为所有类都是Object的子类所以可以同过别的方式达到继承的效果;继承可分为三种方式:
- 利用prototype实现伪继承
- 构造器实现伪继承
- 使用call与apply实现伪继承
prototype
prototype其实是所有类都包含的一个属性,可以用该属性为类增加属性、方法,可视为类的扩展
当类定义实例时,系统就会为其创建每一个该类里面的属性、方法(视包含而定),对于属性,每个实例对象都是不同的,所以应该占用独立的内存,但是对于函数,所有函数的操作方式都是一样,但是系统却为每一个相同的函数分配了独立的内存,这是,就造成了内存的泄漏(浪费)引起性能下降,但是该方法又是字需要一个生意引入了prototype
<script type="text/javascript">
// 定义简单函数
function Person(name)
{
this.name = name;
function f()
{
alert(this.name);
}
}
</script>
<script type="text/javascript">
// 定义简单函数
function Person(name)
{
this.name = name;
}
Person.prototype.f = function()
{
alert(this.name);
}
</script>
上面两段不同的创建函数的代码,效果是一样的,但是第一个造成了内存的泄漏,生意使用第二个
由于prototype是系统只定义了一个函数,这里可以和Java里面的静态函数做比较,当使用prototype时,就相当于Java里面的静态函数,不使用时,相当于Java里面的普通函数
prototype实现继承
<script type="text/javascript">
// 定义一个Person类
function Person(name)
{
this.name = name;
}
// 使用prototype为Person类添加sayHello方法
Person.prototype.sayHello = function()
{
console.log(this.name + "正在学习!");
}
var per = new Person("aile", 22);
per.sayHello(); // 输出:aile正在学习!
// 定义一个Student类
function Student(age){
this.age = age;
}
// 将Student的prototype设为Person对象
Student.prototype = new Person("未命名");
// 使用prototype为Student类添加intro方法
Student.prototype.intro = function(){
console.log("%s是个学生,年龄是%d岁" , this.name, this.age);
}
var stu = new Student(23);
stu.name = "aile";
console.log(stu instanceof Student); // 输出true
console.log(stu instanceof Person); // 输出true
stu.sayHello(); // 输出:aile正在学习!!
stu.intro(); //输出:aile是个学生,年龄是23岁
</script>
执行结果:
将Person的实例,通过prototype给Student,相当于Student增加了属性,实现了一种继承由于函数的独立性,里面所有包含this的赋值,都是随对象走,所以虽然Person里面的赋值写着this.name=name,但是当Student的实例调用时,这个this也就相当于Studnet的实例,
构造器实现伪继承
<script type="text/javascript">
// 定义一个Person类
function Person(name,age)
{
this.name = name;
this.age = age;
}
// 使用prototype为Person类添加sayHello方法
function Studnt(name,age,sex)
{
this.temp=Person;
this.temp(name,age);
this.sex=sex;
}
var stu = new Studnt("aile",23,"男");
alert(stu.name + "\n" + stu.age + "\n" + stu.sex);
</script>
将Person函数名赋值给this.temp;然后再在this.temp给Person传值,这样就达到另一种继承
这种继承,因为白话一点,就相当于在Student里面调用了Person,所以,当执行
stu instanceof Person时,返回的是false(stu是Student的实例对象);而prototype实现的继承将Student的原型设为了Persons所以返回了true;
使用apply()或call实现伪继承
<script type="text/javascript">
function Person(name,age)
{
this.name = name;
this.age = age;
function info()
{
console.log("姓名:" + this.name + ",年龄:" + this.age);
}
}
function Student(name,age,sex)
{
Person.call(this,name,age);
//Person.apply(this,[name,age]);
this.sex=sex;
}
var stu = new Student("aile",23,"男");
console.log(stu instanceof Student); // 输出true
console.log(stu instanceof Person); // 输出false
stu.info(); //输出:姓名:aile,年龄:23
</script>
这里调用者是this,即当Student实例化对象时,这个this就代表着这个对象,所以也实现了一种伪继承;和上面的一样,相当于是调用了Person函数,所以也是伪继承,所以stu instanceof Person返回值也是false;