1.类
在javascript语言中,生成实例对象使用构造函数;ES6提供了类Class这个概念,作为对象的模板。定义一个类通过class关键字,ES6的类可以看成是构造函数的另一种写法。
ES5 如何继承 实例使用属性和方法 1.从实例对象本身查找属性或者方法 2.如果实例没有,从构造函数的原型对象中找 3.如果还没有,从父构造函数的原型对象中找
function Person(){} Person.prototype={}; var p1=new Person(); p1.sayName=function(){}; p1.sayName(); //p1去调用sayName,自身有访问自身,自身没有访问构造函数原型对象,构造函数原型对象没有去找父构造函数
1.经典继承 function Animal(type,age,weight,length){ this.type=type; this.age=age; this.weight=weight; this.length=length } Animal.prototype={ constructor:Animal, sayType:function(){ console.log(this.type) } } function Dog(type,age,weight,length,name,color){ // 经典继承又称为构造函数继承 Animal.call(this,type,age,weight,length); this.name=name; this.color=color; } 处理完构造函数处理原型对象 2.//原型链继承 Dog.prototype=new Animal(); Dog.prototype.constructor=Dog; Dog.prototype.sayColor=function(){ console.log(this.color) } var d1=new Dog('狗',1,'10kg','40cm','可乐','白色'); console.log(d1); d1.sayType(); d1.sayColor();
ES6 1.如何定义一个类 class Person{ constructor(name,age){ this.name=name; this.age=age } sayName(){ //--类似于存在类的原型对象中 console.log(this.name) } } 2.constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。通过static关键字来定义静态属性和静态方法。 class Person{ } => class Person{ constructor(){} } 3.定义在类体的方法称为实例方法,其实是存在于Person.prototype中,可供所有的实例调用。 class Person{ constructor(name,age){ this.name=name; his.age=age } sayName(){ //--- 其实可以理解为存在于Person.prototype中 console.log(this.name) } } 4.静态方法 通过static关键字来定义静态属性和静态方法。也可以在外侧添加静态属性;静态属性和静态方法是定义在类【构造函数】上的,所以可以通过类【构造函数】直接访问。在静态方法中,this指向当前类【构造函数】 class Person{ //静态属性是构造函数私有属性 并不是公共属性 static test=['hello'];//可以是引用数据类型 static test1='hello';//可以是基本数据类型 test3=[];---实例私有属性 //静态方法 static sayName(){ return this.test3 } }
class Person{ //构造器 默认有一个,可以显式提供 constructor(name,age){ // 实例的私有属性 this.name=name; this.age=age; } // 实例私有属性 test=['hello'] // 实例的方法 原型对象中的方法 sayName(){ console.log(this.name) } // 静态方法 static sayType(p){ return p instanceof Person } //静态属性 static gende='男' }; let p=new Person('zhangsan',12); let p2=new Person({}); p.test.push('tom') console.log(p,p2);//维护的是私有属性 创建的是不同子类构造函数对象 p.sayName(); console.log(Person.sayType(p));//静态方法由类去调用 console.log(p.test===p2.test);//私有属性不相同 console.log(p.sayName===p2.sayName)//存放在原型对象中的是同一个方法 实例方法和实例属性写在哪 实例可以调用的方法和属性 静态方法和静态属性写在哪 类本身调用的方法和属性
2.继承
class可以通过extends关键字实现继承,子类可以没有构造函数,系统会默认分配。子类提供了构造函数则必须要显式调用super。super函数类似于借用构造函数。类似于Animal.call()
1.子类对象指向父类对象
2.子类原型对象继承父类原型对象
class Animal{ // 静态属性 static animalAttr='Animal的静态属性'; constructor(name,age,weight){ this.name=name; this.age=age; this.weight=weight; } // 实例方法 sayName(){ console.log('实例方法') } // 静态方法 static animalmethod(){ console.log('Animal静态方法') } } // 要实现继承 class Dog extends Animal{ constructor(name,age,weight,color){ super(name,age,weight); this.color=color; console.log('Dog的构造器') } } let dog=new Dog('豆豆',1,10,'golden'); // 继承 子类的原型对象继承父类的原型对象 dog.sayName(); // 继承 子类的对象通过__proto__指针指向父类的对象 Dog.animalmethod(); console.log(Dog.animalAttr); console.log(Dog.__proto__===Animal); console.log(Dog.prototype.__proto__===Animal.prototype)
3.Symbol
ES6引入的一种新的原始数据类型Symbol,表示独一无二的值。Symbol函数可以接受参数,表示对于这个唯一值的描述。属于基本数据类型,Symbol()函数会返回symbol类型的值
// 创建symbol值 let sy1=Symbol('hello'); let sy2=Symbol(); console.log(sy1==sy2); ###1. 为了解决冲突 let obj={ name:'zhangsan', age:12 } // 新增属性 修改属性 let sy3=Symbol('name'); let obj1={ ...obj, // 属性名是变量名时使用中括号 [sy3]:"myname" } console.log(obj1) 案例: let sy1=Symbol('age'); let sy2=Symbol('name'); let obj={ name:"zhangsan", age:12, [sy1]:'myname', [sy2]:'myage', [Symbol('email')]:'kangjie@briup.com' } for(let key in obj){ console.log(key); } let ss=Object.getOwnPropertySymbols(obj); console.log(obj[ss[2]]);
2.消除魔术字符串 魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。
function test(shape,options){ let area=0; switch(shape){ case Shape.SJX: area=.5 * options.width*options.height break; case Shape.ZFX: area=options.width*options.height break; case Shape.CIRCLE: area=Math.PI*Math.pow(options.r,2) break; default: area=-1 } return area } let Shape={ SJX:Symbol('sjx'), ZFX:Symbol('zfx'), CIRCLE:Symbol('circle') } let res=test(Shape.SJX,{width:100,height:100,r:100}); console.log(res);
3.全局注册表 Symbol() 不同的是,用 Symbol.for() 方法创建的的 symbol 会被放入一个全局 symbol 注册表中。Symbol.for() 并不是每次都会创建一个新的 symbol,它会首先检查给定的 key 是否已经在注册表中了。假如是,则会直接返回上次存储的那个。否则,它会再新建一个。
// 将symbol放到全局注册表中 let sy1=Symbol.for('hello'); // 从全局注册表中找到该key对应的value let sy2=Symbol.for('hello'); console.log(sy1===sy2);//true // 每次都会创建一个不同symbol值 虽然描述符一样 但是Symbol value值不一样 let sy3=Symbol('hello'); let sy4=Symbol('hello'); console.log(sy3==sy4);//false Symbol.keyFor() // Symbol.keyFor()可以检测symbol值是否在全局注册表中注册过。 返回对于symbol的描述或者undefined let sy1=Symbol.for('hello'); console.log(Symbol.keyFor(sy1)); let sy2=Symbol('world'); console.log(Symbol.keyFor(sy2))