欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS(四)中级

程序员文章站 2022-05-08 16:51:19
...

一、引言

思维角度:以一个Java开发的程序员的视觉,思考JS面向对象语言的特点

思考1:JS是面向对象的语言,但是没有类的概念,如何创建对象?

思考2:JS是面向对象的语言,但是没有类,怎么继承

二、解决问题

问题1:没有类,如何创建对象?

理解:JS虽然没有类库,也没有class,所以无法通过类的形式创建对象。但是,我们直到对象的本质无非是属性加上方法吗?

例1  一个对象的创建

     var animal={
	        	name:"animal",
	        	eat:function(){
	        		console.log(this.name+" is eating");//向控制台输出内容
	        	}
	        };
	        animal.eat();//调用函数

补充:由于对象的并并不和类关联,可以随意的给这个对象添加属性

例2  添加属性

        <script type="text/javascript">
	        var animal={
	        	name:"animal",
	        	eat:function(){
	        		console.log(this.name+" is eating");//向控制台输出内容
	        	}
	        };
	        animal.eat();
	        animal.color="black";//给对象添加新属性
	        console.log(animal.color);
	</script>

至此:对象创建出来了,但是对象太*了(思考:弊端是什么?)

问题2:没有类怎么继承?

理解:继承无非是让类与类建立关联,那么如何建立关联呢?

关联方式:JS中的每一个对象都有一个特殊的属性"__proto__",通过此属性去关联另外一个对象,这个对象就是所谓的原型

例3

<script type="text/javascript">
	        //(1)创建一个对象(非new的形式)
	        var animal={
	        	name:"animal",
	        	eat:function(){
	        		console.log(this.name+" is eating");//向控制台输出内容
	        	}
	        };     
	        animal.color="black";//对象中添加一个属性
	        
	        //(2)创建一个对象
	        var dog={
	        	name:"dog",
	        	__proto__:animal //指向animal对象
	        };
	        //(3)创建一个对象
	        var cat={
	        	name:"cat",
	        	__proto__:animal //指向animal对象
	        };
	        dog.eat();//继承原型的方法
	        cat.eat();//继承原型的方法
	        console.log(dog.name);//dog   --覆盖原型的属性
	        console.log(cat.name);//cat   --覆盖原型的属性
	        console.log(cat.color);//black--继承原型的属性
</script>

分析:cat和dog对象的原型都是animal,但是其对象里面都没有定义eat方法,那么是如何调用的呢?

过程:当eat方法被调用时,首先会在自己(调用对象)的方法列表中寻找,如果找不到,则去原型中寻找,如果仍找不到继续往上

层的原型中去寻找,直到找到了Object那里,任然找不到,则就是未定义(undifined)。几个对象会通过__proto__建立如下的

型链(作用:函数复用)

JS(四)中级

回顾:JVM虚拟机中,一个对象在执行方法的时候,整个流程:也是先查找方法的定义,查找次序:先从本对象所属的类开始,

然后是父类,祖父类,直到Object,思路是一样的。

补充:关于JS属性的属性,也是如此通过原型链查询的

三、向Java靠拢

我们知道JS本来全名叫LiveScript,为了搭上Java帝国的快班车,改名为JavaScript,向Java示好。

模仿Java的类定义、创建对象、以及调用方法。

具体表现

例4

                        function Student(name){
				this.name=name,//也可以变成;号,但是JSON形式封装数据不行
				this.hello=function(){
					console.log("I am "+this.name);
				}
			}
			 var jane=new Student("jane");//创建对象(var可以省略!!!)
			 var tony=new Student("tony");//创建对象(hello定义在此对象中,意味着该对象有此方法的实体)
			 jane.hello();//I am jane
			 tony.hello();//I am tony

示好说明:提供了一个家叫做构造函数的东西,可以看到function有点类似class的感觉(雏形),并且有this关键字,而且Student

,整个感觉就像是一个Java类

上面出现小问题:每个新创建的对象都有一个hello函数,函数定义在对象上,意味着每个对象都有一份太浪费

高效的解决方法:把hello函数放到自己创建的原型对象中去,然后让jane、tony这些从Student中创建而来的对象指向这个原型

如何指向呢?把原型对象放到Student.prototype这个属性中

例5

<script type="text/javascript">   
			function Student(name){
				this.name=name;
			}
			//重点在这!!!
			Student.prototype={
				hello:function(){
					console.log("I am "+this.name);
				}
			}
			 var jane=new Student("jane");//创建对象
			 var tony=new Student("tony");//创建对象
			 jane.hello();//I am jane
			 tony.hello();//I am tony
</script>

特点:每次通过Student创建的对象(jane、tony),JS会自动建立原型链

具体分析:new Student的时候,JS会建立如下的关系链:

JS(四)中级

实质:所谓的构造函数Student就是一个幌子,每次通过"new Student"创建对象,并且把该对象的原型(__proto__)指向

Student.prototype这个原型对象,这样就能找到hello()方法。

理论基础:当一个对象调用方法的时候,会顺着原型链向上寻找。

四、向Java程序员示好(了解即可)

由于上述的构造函数再加上prototype的概念,让人很是费解,JS提供了一些语法糖来降低程序员(Java)的负担。

例6

                    //重点是class
			class Student(name){
				this.name=name,
				this.hello=function(){
					console.log("I am "+this.name);
				}
			}
			var jane=new Student("jane");//创建对象
			var tony=new Student("tony");//创建对象
			jane.hello();//I am jane
			tony.hello();//I am tony

说明:语法糖已经把JS变得非常像Java(C#、C++)的类了。

注意:class是ES 2015的新特性

思考:原型法对于Java、C#、C++码农不是很直观,引入类的语法糖能吸引更多的码农加入JS王国,但是JS是否远离了初衷?

四、JSON

理解JOSN封装数据是封装一种格式,这种格式也被其他语言也采用了 。

特点:JSON采用键值对的方式去封装数据(非二进制流);应用场景:JOSN数据占用比较小,一般用于网络传输、交换数据

说明:JSON中的引号括起来,如果是字符串也用引号括气来(数字不括)

应用1:标准JSON数组的遍历

<script type="text/javascript">
		//(1)定义JSON的数组对象
		    var JSON={
		    	name:"jane",
		    	age:18,
		    	agender:"male"
		    };
		    document.write(typeof JSON);
		//(2)遍历JSON数组--特有的for in的形式
		for(var i in JSON){
			console.log(JSON[i]);
		}
	         //表示遍历数组,而i表示的是数组的下标值,
                 //JSON[i]表示获得第i个数据
</script>

注意:for in循环的用法(里面参数的含义),普通的for循环方法

应用2:复杂的标准JSON格式的数组遍历(嵌套)

需求:获取相同JSON格式中的某个字段的内容

//(1)定义JSON的数组对象(嵌套)
	var JSON=[
	{"flag":1,"age":18,"phone":"110","userName":"小红"},
	{"flag":0,"age":20,"phone":"119","userName":"小明"}];
	//(2)遍历JSON数组--for in的形式
	for(var i in JSON){
		console.log(JSON[i].userName);
	//result[i]表示获得第i个json对象即JSONObject
        //result[i].字段名称--即可获得指定字段的值
}

应用3:复杂的非标准JSON格式的数组遍历(嵌套)

<script type="text/javascript">
		//(1)定义非标准的JSON的数组对象(嵌套)
		 var JSON = {
				"name": "张三",
				"age": 23,
				"sex": "男",
				"score": {
					"chinese": 100,
					"math": 90,
					"english":85
				}
			};
        //(2)遍历数据
        for(var i in JSON){
        	//重要:通过typeof 把object转成一个字符串的"object"
			var v = typeof JSON[i];
			if(v=="object"){
				//表明又是一个JSON格式的数据,则获取出这个嵌套的json对象 再次进行遍历
				var innerJSON= JSON[i];
				for(var j in innerJSON){
					console.log(innerJSON[j]);
				}
			}else{
				//说明是基本类型的数据
				console.log(JSON[i]);
			}
        }
</script>
	

应用4:复杂的非标准JSON格式的数组遍历(嵌套)

            var JSON={
			"datas":
			[{"flag":1,"macId":"2","mbId":0,"userName":"XXX"},
			{"flag":1,"macId":"1","mbId":1,"userName":"YYY"}]
			};
			//说明:进行遍历之前得先解析出标准的json数组格式即[{},{}]
			var json=JSON.datas;
			for(var i in json){
			//表示遍历数组,而i表示的是数组的下标值,
        		//data[i]表示获得第i个json对象即JSONObject
        		//data[i]通过.字段名称即可获得指定字段的值
        		console.log(json[i].userName);
			}

相关链接:点击打开链接点击打开链接

应用5:对一个内置对象进行一个功能上的扩展(原型属性)

需求:数组本身没有排序的功能,给其内置一个函数,进行功能性的扩展

1、书写一个MyArray.js的文件

Array.prototype.getMax = function() {
	var max = this[0];//谁调用this就是谁
	for(var i = 1; i < arr.length; i++) {
		if(this[i] > max) {
			max = this[i];
		}
	}
	return max;
}

2、调用函数

<script src="js/MyArray.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			var arr=[10,60,80,90,100];
			var max=arr.getMax();//调用扩展的功能
			alert(max);
			arr.reverse();
			alert(arr);
</script>

注意:扩展方式的书写(两种)

五、延伸

继承链和类加载器的联系、sublime

JS的异步调用比Java的注册监听器好多

原生JS

JS的调试,通过控制台(Google--检查--Console)

相关标签: 原型