JavaScript面向对象

x33g5p2x  于2021-10-07 转载在 JavaScript  
字(8.2k)|赞(0)|评价(0)|浏览(395)

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>

创建原型对象(常用)

在上面的创建方法 都有各自的缺陷 比如直接创建的对象 无法复用 使用模板创建的对象就无法数据共享了

我们就可以使用原型对象 来满足这个要求 既能复用 还能共享

演示:

需要创建一个空模板

内部不需要添加任何东西 否则报错 就是一个空函数就行了
1.
给模板添加 属性和方法

语法:模板名称.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

可以发现类型 也变了 变成 转换后的类型

相关文章