JavaScript面向对象
什么是面向对象 学过java的都懂 简单来说就是将 变量 方法 等 封装到对象里
我们在其他地方 只需要通过这个对象就能调用 对象里的 内容
用法也和java 差不多
创建对象的三种方法
第一种 通过new Object(); 来创建对象的方式
<script>
//第一种创建对象的方式 属性和方法 都用引号隔开
var flpwer = new Object();
//给对象添加 属性
flpwer.name = "长花村";
flpwer.genera = "鸡爪萨达";
//给对象添加方法
flpwer.show = function() {
alert(this.name);
}
flpwer.show1 = function() {
alert(this.genera);
}
//调用对象内的方法
flpwer.show();
</script>
第二种 创建对象的方式 使用{ }
<script type="text/javascript">
//第二种创建对象的方法 属性 和方法 都要用逗号隔开
var flower = {
name: "hello",
gender: "男",
show: function() {
var str = this.name + "<br>" + this.gender
document.write(str);
},
show1: function() {
alert("你好")
}
}
//调用 对象内的方法
flower.show()
</script>
第三种方式 模板方式
我们可以观察上面案例中 创建对象的2种方式 都是直接生成一个对象了
而我们修改直接就是在修改这个对象内的数据 就和java中被 static 修饰的属性感觉一样
这样的好处就是 可以实现数据同步 在某一个地方 将此对象内的数据修改后 其他调用的地方都会被修改
但是在很多情况下 都不需要数据同步 但是我也不想在创建一个新的了 怎么办 ?
很简单 我们可以 先创建一个模板 就行了
<script type="text/javascript">
//创建一个模板
function Flower() {
this.name;
this.gender="男";
//给模板添加 方法
this.show = function() {
alert("姓名:"+this.name+"___"+"年龄:"+this.gender);
};
}
// 创建对象 1
var f= new Flower();
f.name="hell"
f.show()
// 创建对象 2
var f1= new Flower();
f1.name="abc"
f1.show()
</script>
创建原型对象(常用)
在上面的创建方法 都有各自的缺陷 比如直接创建的对象 无法复用 使用模板创建的对象就无法数据共享了
我们就可以使用原型对象 来满足这个要求 既能复用 还能共享
演示:
-
需要创建一个空模板
内部不需要添加任何东西 否则报错 就是一个空函数就行了
-
给模板添加 属性和方法
语法:模板名称.prototype.属性或方法
//创建一个空模板
function Flower() {}
//给模板 添加属性
Flower.prototype.name ;
Flower.prototype.gender = "男";
//给模板添加 方法
Flower.prototype.show = function() {
alert("姓名:"+this.name+"___"+"年龄:"+this.gender);
}
//创建对象
var flower1 = new Flower();
//给对象 赋值
flower1.name="曼陀罗";
//调用对象内的 方法
flower1.show()
var flower2 = new Flower();
flower2.name="白鹤湖";
flower2.show()
我们想要通过模板模型 实现数据同步怎么办 就和java中被static修饰的 效果一样
语法:
模板名称.prototype.属性或者方法 等同于java中的 类名.属性或者方法
这种方式 是全局共享的 和对象无关
演示:
<script type="text/javascript">
//创建一个模板
function Flower() {}
//给模板 添加属性
Flower.prototype.name ;
Flower.prototype.gender = "男";
//给模板添加 方法
Flower.prototype.show = function() {
alert("姓名:"+this.name+"___"+"年龄:"+this.gender);
}
// 静态的调用方式
Flower.prototype.name = "长存2312";
Flower.prototype.name = "长存";
Flower.prototype.show()
//对象调用方式
var f1=new Flower();
f1.name="hell";
f1.show()
</script>
总结:
**定义方式: **原型对象和普通对象 在定义方面的区别 就是 原型对象必须在模板后面手动声明prototype的方法
而普通对象直接在模板内部定义普通方法就行
调用方式 : 如果没有使用 prototype定义方法那么 调用的时候也就不能使用 prototype来调用方法
构造对象
构造就和 java使用效果一样 主要作用就是能在 new 对象的时候进行初始化
在js 中 构造参数不必都进行赋值 当然也可以指定默认值
普通构造对象
<script type="text/javascript">
//创建构造对象
function Fow(name, gender = "男") {
//创建属性 this就是指向这个新的对象属性
this.name = name;
this.gender = gender;
//创建方法 this就是指向这个新的对象方法
this.show = function() {
alert(this.name + "___" + this.gender);
}
}
//给构造赋值
var fow1 = new Fow("haha");
//调用对象方法
fow1.show();
//给构造赋值
fow1 = new Fow("ha", "女");
//调用对象方法
fow1.show();
</script>
原型构造对象
和普通构造的区别就是 方法不能在内部定义 必须在外部指定 prototype
<script type="text/javascript">
//创建构造对象
function Fow(name, gender) {
//创建属性 this就是指向这个新的对象属性
this.name = name;
this.gender = gender;
}
//创建方法 this就是指向这个新的对象方法
Fow.prototype.show = function() {
alert(this.name);
}
Fow.prototype.name = "hello"
Fow.prototype.show()
var f1=new Fow("word");
f1.show()
</script>
断对象类型
在 JavaScript 中, 判断一个变量的类型尝尝会用 typeof 运算符, 在使用 typeof 运算符时采用引用类型存储值会出现一个问题, 无论引用的是什么类型的对象, 它都返回“ object”。 ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。 instanceof 运算符与 typeof 运算符相似, 用于识别正在处理的对象的类型
<script type="text/javascript">
function Fow(name,gender){
//创建属性
this.name=name;
this.gender=gender;
}
//给将带参函数赋值 并且 给一个对象
var fow1=new Fow("haha","男");
var fow2=new Fow("ha","男");
document.write(fow1 instanceof Fow); //true
document.write(fow1 instanceof Object); //true
</script>
原型链(继承)
就和java中的逻辑一样 就是语法不同而已
普通对象方式继承
<script type="text/javascript">
//创建一个模板
function Flower() {
this.name="hu";
//给模板添加 方法
this.Name = function() {
alert("姓名:"+this.name+"___");
};
}
function Flower1() {
this.gender="男";
//给模板添加 方法
this.Genter= function() {
alert("年龄:"+this.gender);
};
}
Flower1.prototype=new Flower();
var ff1=new Flower1();
ff1.Name()
ff1.Genter()
</script>
原型对象继承
//创建一个原型Humans
function Humans() {
this.foot = 2;
}
//给原型添加 方法
Humans.prototype.getFoot = function() {
return this.foot;
}
//创建一个原型Man
function Man() {
this.head = 1;
}
Man.prototype.getHead = function() {
return this.head;
}
// 使Man原型继承 Humans所有
Man.prototype = new Humans(); //Map 继承了 Humans的所有
var man1 = new Man();
document.write(man1.getFoot() + "<br>") //使用map 读取Humans 里面 的 getFoot方法 结果 2
document.write(man1.getHead() + "<br>") //读取自身 的 getHead方法 结果 1
//进行判断 判断 man1是否是 Humans的实现类 或者是其子类
document.write(man1 instanceof Humans, "<br>") //true
//进行判断 判断 man1是否是 Man的实现类 或者是其子类
document.write(man1 instanceof Man) //true
重写方法
子类继承父类 有时候要重写父类 的方法 或者 添加新的方法 但是不管怎么样 给原型添加方法的代码一定要放在 继承语句的后面
普通对象
<script type="text/javascript">
//定义父类
function Humans() {
this.foot = 2;
//给父模板创建方法
this.getFoot = function() {
return this.foot;
}
}
//定义子类
function Man() {
this.head = 1;
//给Map添加新的方法
this.getHead = function() {
return this.head;
}
}
//Map 继承了 Humans的所有
Man.prototype = new Humans();
//重写父类方法 要和父类的方法名一样
Man.prototype.getFoot = function() {
//使用本类的 属性
return this.head;
}
var man1 = new Man();
//调用重写后的Man里的getFoot方法 不是调用Humans里的getFoot方法
document.write(man1.getFoot()) //结果1
</script>
原型对象
<script type="text/javascript">
//定义父类
function Humans() {
this.foot = 2;
}
//给父模板创建方法
Humans.prototype.getFoot = function() {
return this.foot;
}
//定义子类
function Man() {
this.head = 1;
}
//Map 继承了 Humans的所有
Man.prototype = new Humans();
//给Map添加新的方法
Man.prototype.getHead = function() {
return this.head;
}
//重写父类方法 要和父类的方法名一样
Man.prototype.getFoot = function() {
//使用本类的 属性
return this.head;
}
var man1 = new Man();
//调用重写后的Man里的getFoot方法 不是调用Humans里的getFoot方法
document.write(man1.getFoot()) //结果1
</script>
解决数组在对象之间数据同步问题
继承 数组时候 会出现的问题<br>
<script type="text/javascript">
function Humans() {
this.foot = 2;
this.cloo = ["sadsa", "dadsff"];
}
Humans.prototype.getFoot = function() {
return this.foot;
}
function Man() {
this.head = 1;
}
//Map 继承了 Humans的所有
Man.prototype = new Humans();
var man1 = new Man();
//给man1对象内的数组添加值
man1.cloo.push("ggg");
var man2 = new Man();
document.write(man1.cloo + "<br>");
document.write(man2.cloo)
</script>
结果:
//sadsa,dadsff,ggg
//sadsa,dadsff,ggg
可以发现我只在man1 对象中添加了ggg 我man2 怎么也出现了ggg 因为数组是对象
我们保存的只是地址而已 这就会造成 所有对象的数组地址 都是一样 也就是说某一个对象 修改了 数组
那么其他 对象中的数组也发生变化了
为了解决此问题 出现了借用构造函数
使用 父类.call(this,”参数1”,”参数2” ………) 调用父类的带参函数
和java中的super()一样的效果 调用父类构造
无参构造
<script type="text/javascript">
//创建父类
function Humans() {
this.coo = ["dsadaf", "fagga"];
}
//创建子类
function Man() {
//调用父类无参构造
Humans.call(this);
//定义属性
this.name="abc";
}
//对象1
var man1 = new Man();
man1.coo.push("aaaa");
//对象2
var man2 = new Man();
console.log(man1.coo );
console.log(man2.coo)
console.log(man2.name)
</script>
结果:
[“dsadaf”, “fagga”, “aaaa”]
[“dsadaf”, “fagga”]
abc
<script type="text/javascript">
//父类
function Humans(age) { //带参
this.coo = ["dsadaf", "fagga"];
this.age=age;
}
//子类
function Man(name,age) {
//调用父类带参构造
Humans.call(this, age);
//定义属性
this.name=name;
}
//对象1
var man1 = new Man("hell",12);
man1.coo.push("aaaa");
console.log(man1.coo );
console.log(man1.name)
//对象2
var man2 = new Man("wolr",14);
console.log(man2.coo)
console.log(man2.name)
</script>
结果:
[“dsadaf”, “fagga”, “aaaa”]
hell
[“dsadaf”, “fagga”]
wolr
继承 的向上转型 向下转型 (多态)
和java一样的效果 前提必须保证是继承关系 否则就会报错了
向下转型
创建一个父类对象 然后在创建一个子类对象 将父类对象付给子类对象
向上转型
创建一个父类对象 然后在创建一个子类对象 将子类对象付给父类对象
<script type="text/javascript">
function Humans(name){
this.name=name;
}
Humans.prototype.sayname=function(){
console.log(this.name);
};
function Man(name,age){
Humans.call(this,name); //继承构造
this.age=age;
}
// Man 继承 Humans
Man.prototype=new Humans();
//创建父类对象
var hu=new Humans("hu");
//创建子类对象
var man=new Man("wo",12);
man.sayname() //wo
//----------父向子转--------向下转型
man=hu
man.sayname() //hu
//-----------子向父转----- 向上转型
hu=man
hu.sayname() //hu
</script>
是不是感觉 好像 是覆盖了 但是 其实并没有
我们来判断先对象的类型
//创建父类对象
var hu=new Humans("hu");
//创建子类对象
var man=new Man("wo",12);
man.sayname() //结果wo
//----------父向子转--------向下转型
man=hu
man.sayname() //结果hu
console.log(man instanceof Humans)//true
console.log(man instanceof Man)//false
//-----------子向父转----- 向上转型
hu=man
hu.sayname() //hu
console.log(hu instanceof Humans)//true
console.log(hu instanceof Man)//false
可以发现类型 也变了 变成 转换后的类型