JS对象模型
定义类
字面式声明方式
ES6之前---构造器
//定义类 function Point(x,y){ this.x = x; this.y = y; this.show = () => console.log(this,this.x,this.y); console.log('Point~~~~~~'); } // console.log(Point) //[Function: Point] // p1 = Point(4,5) // console.log(p1) //undefined p1 =new Point(4,5) //Point~~~~~~ console.log(111,p1) //Point { x: 4, y: 5, show: [Function] } //继承 function Point3D(x,y,z){ Point.call(this,x,y); this.z = z; console.log('Point3D~~'); } console.log(222,Point3D); //[Function: Point3D] p2 = new Point3D(14,15,16); //Point~~~~~~ Point3D~~ console.log(333,p2); //Point3D { x: 14, y: 15, show: [Function], z: 16 } p2.show(); //Point3D { x: 14, y: 15, show: [Function], z: 16 } 14 15
ES6中的class
//基类定义 class Point{ constructor(x,y){/*构造器*/ this.x = x; this.y = y; } show(){/*方法 */ console.log(this,this.x,this.y); } } let p1 = new Point(10,11) p1.show() //Point { x: 10, y: 11 } 10 11 //继承 class Point3D extends Point{ constructor(x,y,z){ super(x,y) this.z = z } } let p2 = new Point3D(20,21,22) p2.show() //Point3D { x: 20, y: 21, z: 22 } 20 21
重写方法
//基类定义 class Point{ constructor(x,y){/*构造器*/ this.x = x; this.y = y; } show(){/*方法 */ console.log(this,this.x,this.y); } } let p1 = new Point(10,11) p1.show() //Point { x: 10, y: 11 } 10 11 //继承 class Point3D extends Point{ constructor(x,y,z){ super(x,y) this.z = z } show(){/*方法 */ console.log(this,this.x,this.y,this.z); } } let p2 = new Point3D(20,21,22) p2.show() //Point3D { x: 20, y: 21, z: 22 } 20 21 22
//基类定义 class Point{ constructor(x,y){/*构造器*/ this.x = x; this.y = y; this.show = () => console.log('Point'); // this.show = function (){console.log(this,this.x,this.y)}; } } //继承 class Point3D extends Point{ constructor(x,y,z){ super(x,y) this.z = z this.show = () => {console.log('Point3D')} } } let p2 = new Point3D(20,21,22) p2.show() //Point3D
class Point{ constructor(x,y){ this.x = x; this.y = y; this.show = () => console.log('Point'); } // show (){/*方法*/ // console.log(this,this.x,this.y); // } } //继承 class Point3D extends Point{ constructor(x,y,z){ super(x,y); this.z = z; } show (){//重写 console.log('Point3D'); } } let p2 = new Point3D(20,21,22); p2.show() //Point
class Point{ constructor(x,y){ this.x = x; this.y = y; // this.show = () => console.log('Point'); } // show (){/*方法*/ // console.log(this,this.x,this.y); // } } let p1 = new Point(10,11) p1.show() console.log('~~~~~~~~~~~~~~~~') //继承 class Point3D extends Point{ constructor(x,y,z){ super(x,y); this.z = z; this.show = () => console.log('Point3D'); } } let p2 = new Point3D(20,21,22); p2.show() //Point3D
静态属性
class Add{ constructor(x,y){ this.x = x; this.y = y; } static print(){ console.log(this.x)// this是Add,而不是Add的实例 } } add = new Add(40,50); console.log(Add); // [Function: Add] Add.print(); //undefined // add.print(); //实例不能直接访问静态方法,和C++、Java一致 add.constructor.print() //undefined 实例可以通过constructor访问静态方法
this的坑
var school = { name:'magedu', getNameFunc:function(){ console.log(this.name); console.log(this); return function(){ console.log(this === global);//this是否是global对象 return this.name } } } console.log(school.getNameFunc()()) //运行结果: // magedu // { name: 'magedu', getNameFunc: [Function: getNameFunc] } // true // undefined
分析上例
//1.显示传入 // console.log(1,school.getNameFunc()(school)) // return function(that){ // console.log(this === global);//this是否是global对象 // return that.name // }
//2.引入apply、call方法 // console.log(school.getNameFunc().call(school)); // console.log(school.getNameFunc().apply(school));
function Print(){ this.print = function(x,y){console.log(x+y)}; } p = new Print(1,2) console.log(p) //object console.log(typeof p) //Print { print: [Function] } p.print(10,20) //30 p.print.call(p,10,20) //30 p.print.apply(p,[10,20]) //30
//3.ES5引入了bind方法(bind方法来设置函数的this值) // console.log(school.getNameFunc().bind(school)) //[Function: bound ] var func = school.getNameFunc().bind(school) //bind绑定返回新的函数 console.log(func) console.log(func())
//4.ES6引入支持this的箭头函数 // console.log(school.getNameFunc()()) // return () =>{ // console.log(this === global);//this是否是global对象 // return this.name // }
高阶对象、高阶类、或称Mixin模式
继承实现
class Serialization{ constructor(){ console.log('Serialization constructor~~~'); if (typeof(this.stringify) !== 'function'){ throw new ReferenceError('should define stringify') } } } class Point extends Serialization{ constructor(x,y){ console.log('Point constructor~~~'); super();//调用父类构造器 this.x = x; this.y = y; } } // s = new Serialization(); //构造Serialization失败 // p = new Point(4,5); //构造子类对象时,调用父类构造器执行也会失败
class Serialization{ constructor(){ console.log('Serialization constructor~~~'); if (typeof(this.stringify) !== 'function'){ throw new ReferenceError('should define stringify') } } } class Point extends Serialization{ constructor(x,y){ console.log('Point constructor~~~'); super();//调用父类构造器 this.x = x; this.y = y; } stringify(){ return `<Ponintx=${this.x},y=${this.y}>` } } class Point3D extends Point{ constructor(x,y,z){ console.log('Point3D constructor~~~'); super(x,y); this.z = z; } stringify(){ return `<Ponintx=${this.x},y=${this.y},z=${this.z}>` } } p = new Point(4,5); console.log(p.stringify()) p3d = new Point3D(1,2,3) console.log(p3d.stringify()) /*运行结果: Point constructor~~~ Serialization constructor~~~ <Ponintx=4,y=5> Point3D constructor~~~ Point constructor~~~ Serialization constructor~~~ <Ponintx=1,y=2,z=3> */
高阶对象实现
//高级对象实现 class A extends Object{}; console.log(A); //[Function: A] //匿名类 const A1 = class{ constructor(x){ this.x = x; } } console.log(A1)//[Function: A1] console.log(new A1(100).x)//100 //匿名继承 const B = class extends Object{ constructor(){ super(); console.log('B constructor'); } } console.log(B); //[Function: B] b = new B(); //B constructor console.log(b); //B {} //箭头函数,参数是类,返回值也是类 //把上例中的Object看成参数 const x = (Sup) => { return class extends Sup{ constructor(){ super(); console.log('x constructor') } } } //演化成下面的形式 const C = Sup => { return class extends Sup{ constructor(){ super(); console.log(`C constructor`) } } } // cls = new C(Object); // 不可以new,因为是一个普通函数,它的返回值时一个带constructor的类 cls = C(A); console.log(cls); //[Function: A] c = new cls() ; //C constructor console.log(c); //A {} //其他写法 c1 = new (C(Object))();//new优先级太高了,所以后面需要加括号才能先调用; console.log(c1); //{}
const Serialization = Sup => class extends Sup{ constructor(...args){ console.log(`Serialization constructor~~`); super(...args) if (typeof(this.stringify) !== 'function'){ throw new ReferenceError('should define stringify'); } } } class Point{ constructor(x,y){ console.log(`Point constructor~~`); this.x = x; this.y = y; } } class Point3D extends Serialization(Point){ constructor(x,y,z){ console.log(`Point3D constructor~~`) super(x,y); //super时Serialization(Point)包装过的新类型 this.z = z; } stringify (){ return `<Point3D ${this.x},${this.y},${this.z}>` } } let p3d = new Point3D(70,80,90); console.log(p3d.stringify); console.log(p3d.stringify());