天天看点

js面向对象、prototype

##js [ECMAScrip+DOM+BOM] 1.js参考 2.es5参考3.实例与对象的区别4.对象与json的区别5.创建对象的若干种方式 6.实例属性类属性实力方法类方法

###js:一种动态类型、弱类型、基于原型的客户端脚本语言,用来给HTML网页增加动态功能。

动态: 在运行时确定数据类型。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。

弱类: 计算时可以不同类型之间对使用者透明地隐式转换,即使类型不正确,也能通过隐式转换来得到正确的类型。

原型(prototype): 自定义的对象继承object对象(作为模版),object将自身的属性共享给新对象,模版对象称为原型。

这样新对象实例化后不但可以享有自己创建时和运行时定义的属性,而且可以享有原型对象的属性。

###ECMAScript(核心)

###BOM

###DOM

1.面向对象(oop)对象参考 es6和es6面向对象区别

面向对象的语言有一个标志,即拥有类的概念,抽象实例对象的公共属性与方法,基于类可以创建任意多个实例对象,一般具有封装、继承、多态(、聚集的特性!

封装 - 把相关的信息(无论数据或方法)存储在对象中的能力
继承 - 由另一个类(或多个类)得来类的属性和方法的能力
多态 - 编写能以多种方法运行的函数或方法的能力
聚集 - 把一个对象存储在另一个对象内的能力
           

但JS中对象与纯面向对象语言中的对象是不同的,ECMA标准定义JS中对象:无序属性的集合,其属性可以包含基本值、对象或者函数。可以简单理解为JS的对象是一组无序的值,其中的属性或方法都有一个名字,根据这个名字可以访问相映射的值(值可以是基本值/对象/方法)。

1)js中一切皆对象:如字符串、数值、数组、函数...;

   js允许自定义类和构建对象(对象构造器[即函数],然后再new一下就ok);
   例:
		#es5的写法,es6有了class关键字
   		function Person(firstname,lastname,age,eyecolor){#Person自定义类
			this.firstname=firstname;
			this.lastname=lastname;
			this.age=age;
			this.eyecolor=eyecolor;
			nation='china'	#类属性
		}
		var myFather=new Person("Bill","Gates",56,"blue");#构建对象
   对象只是带有属性和方法的特殊数据类型;

   基本数据类型(对象):number string boolean null object undefined
	
   基本对象类型(typeof ):number string boolean  object(object、null) fuction undefined
	实例的typeof是object,类(本质是函数,模拟类)的typeof是function


2)实例与对象以及json的与的区别(实例都是对象,对象不一定是实例)【参见链接3,4】
	实例是类的具象化产品
	而对象是一个具有多种属性的内容结构
	理解:
		动物          ---  对象		
		一只狗        ---  实例 (狗具备动物的特征,并且是唯一的,具体的!)
	例:
		var person = new Object(); --实例
		var person = {};--采用对象字面量的方式生成的person,然而它内部没有调用new Object(),而是采用JSON的初始化方式。
	
	json可以点属性,对象也可以点属性。json本质也是对象,一切皆对象。json的key是字符串,json的value可以是指向对象的。
   对于function函数:
	函数实际上就是对象,每个函数都是Function类型的实例,由于函数是对象,
	因此函数名也是指向函数对象的一个指针,并不会和函数绑定

3)创建对象的若干种方式(工厂模式)和单例【参见链接5】
    1.工厂模式:将创建对象的过程抽象为一个函数,用函数封装以特定接口创建对象的细节
	缺点:工厂模式虽然可以创建多个相似的对象,但却不能解决对象标识的问题,即怎样知道一个对象的类型【构造函数解决了这个问题】
			例1:function createStudent(name,sex,grade){                                                         
			    var o = new Object();
			    o.name = name;
			    o.sex = sex;
			    o.grade = grade;
			
			    o.sayName = function(){
			        console.log(this.name);
			    }
			    return o;
			}
			var s1 = createStudent('Claiyre','famale',1);

			例2:function Human(name,age) {
				    this.name=name;
				    this.age=age;
				    this.show=show;
				    nation='china';
				    // return{
				    //     "getNation":function () {
				    //         return nation
				    //     },
				    //     "setNation":function (val) {
				    //         nation=val;
				    //     },
				    //     type:'animal'  //全局类属性
				    // }
				
				}
	2.构造函数模式:在JavaScript中没有类的概念,故不必显式声明某个类,直接创建构造函数即可,类的方法和属性在构造函数中(或原型对象上)处理
	缺点:每个方法都要在每个实例上创建一遍。(也就是说通过构造函数实例化的多个对象的方法,是多个不同的方法,但它们内部的代码以及实现的功能是相同的,这就造成了一定的资源浪费。)
	【这个问题可以用原型模式来解决。】
			function Student(name,sex,grade){                                                   
			    this.name = name;
			    this.sex = sex;
			    this.grade = grade;
			    this.sayName = function(){
			        console.log(this.name);
			    }
			}
			var s2 = new Student('孙悟空','male',2);

	调用构造函数创建对象经过了以下几个过程:
	创建一个新对象
	将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
	执行构造函数中的代码
	返回新对象(不需要显式返回)

	与工厂模式相比,用构造模式创建对象有以下几点不同:
		没有显示地创建对象
		直接将属性和方法赋给this对象
		没有return语句

	3.原型模式:js中每个函数都有prototype属性,它是一个指针,指向prototype原型对象,原型对象包含了所有对象共享的属性和方法。此外原型对象还有一个constructor属性,指向创建对象的构造方法

	function Student_1(){

	}
	Student_1.prototype.name = 'Claiyre';
	Student_1.prototype.sex = 'female';
	Student_1.prototype.class = 5;
	Student_1.prototype.sayName = function (){
	    console.log(this.name);
	}
	
	var s5 = new Student_1();                                                         
	s5.sayName();    //Claiyre
	var s6 = new Student_1();
	s6.sayName();    //Claiyre
	
	4.单例(类只有一个对象):
		var person = {    
			name : 'My name',    
			age : 18,    
			getName : function(){        
				return this.name;  
			  }
		}

4)为实例动态增加删除属性
	delete 类名.属性名 // 或者将属性值设置为undefined
	对象.属性=
5)writable、enumerable和configurable等数据属性
	
	writable : 布尔值,设置属性的值是否可以被重写,false只读
	enumerable : 布尔值,设置属性是否可以被枚举,false(for in时不能被枚举)
	configurable : 布尔值,设置属性是否可以被删除,默认属性值为false(不能被删除)
	????get: 在读取时属性是调用的函数,不设置get方法是默认underfind
	????Set: 在写入取时属性是调用的函数,不设置set方法时默认underfind

6)实例属性,类属性,全局类属性【参见1)和链接6】;实例方法,类方法
	实例属性:this.属性名来访问,(也叫共有属性)[类方法中有this.属性名=属性变量]
	类属性:类名.属性名来访问[构建类属性时,在函数外,类名.属性名=‘’]
	prototype:原型对象共有属性
	 全局类属性:工厂模式中return的属性【实例名.该属性可以】

7)prototype原型(是object类的属性其属性值指向对象,其中包含constructor)[每一个函数对象都有一个prototype属性,但是普通对象是没有的]
	1. protopye与constructor与__proto__
	   prototype属性属于function(从object里继承过来的),prototype属性指向prototype原型对象,该对象包含constructor属性(construct属性指向构造方法,相当于python中的__init__)属性

	2. 为节约内存共有属性和方法应挂载在prototype
	   
	3. 原型继承链:实例属性-->父类的prototype-->object的prototype-->都没有返回undefined
		
8)call和apply实现不相关实例属性和方法继承(本质是借用并非继承)[call,第一个参数是替换对象,其后都是数据传给类方法;apply第一个是替换对象,其后是数组]
	function Teacher() {
	    this.name='teacher'
	}
	
	Teacher.prototype.teach=function () {
	    console.log('i can teach student');
	}
	
	function Student() {
	    this.name='student'
	}
	Student.prototype.study=function () {
	    console.log('i am '+this.name+'i can study it');
	}
	
	var t=new Teacher();
	var s=new Student();
	
	s.study()
	s.study.call(t)

9)伪数组转化为真数组
	function func(a,b,c,d) {
	    console.log(arguments)
	
	    // var args=[];
	    // for(var i of arguments){
	    //     args.push(i)
	    // }
	
	    // arguments.slice(0)
	    // var args=[].slice.call(arguments,0);
	    // var args=(new Array).slice.call(arguments,0);
	    var args=Array.prototype.slice.call(arguments,0);
	    console.log(args.reverse());
	}
	
	// var arr=[1,3,4,2];
	
	
	func(1,2,3,4);



10)instanceof 判断对象的父类,返回true/false:alert(s1 instanceof Student)
   constructor:同一类构建出来的两个对象的construor是一致的:alert(s1.constructor===s2.constructor)
11)use strict
           

###2.es6中的扩展es5基本语法参考!!!es6

会默认采用严格模式

1)变量声明 用let或const代替var
	[在ES6之前,我们都是用var来声明变量,而且JS只有函数作用域和全局作用域,没有块级作用域,所以{}限定不了var声明变量的访问范围]
let:先声明再使用(不会声明提升);不能重复声明;作用域(函数内部)是函数块级元素
const:常量(只读)

2)箭头的使用(箭头函数[相当于lambda表达式]可以替换函数表达式,但是不能替换函数声明)
	注意:如果你在箭头函数中使用了this,那么该this一定就是外层的this。
		 也正是因为箭头函数中没有this,因此我们也就无从谈起用call/apply/bind来改变this指向
	例1:
	// es5
	var fn = function(a, b) {
	    return a + b;
	}
	
	// es6 箭头函数写法,当函数直接被return时,可以省略函数体的括号
	const fn = (a, b) => a + b;
	
	// es5
	var foo = function() {
	    var a = 20;
	    var b = 30;
	    return a + b;
	}
	
	// es6
	const foo = () => {
	   const a = 20;
	   const b = 30;
	   return a + b;
	}
	例2:在ES6中,会默认采用严格模式,因此this也不会自动指向window对象了,而箭头函数本身并没有this,因此this就只能是undefined这种情况,如果还想用this,就不要用使用箭头函数的写法。【参考链接】
	
	3)模板字符串`${}`
	
	4)解析结构
	5)函数默认参数
	6)展开运算符
	7)对象字面量与class
	8)promise
	9)extends
	10)模块modules