We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript是没有类这个概念的,区别于其他传统的强类型语言,例如Java,JS的类(构造函数)在设计根本上就有本质的不同,Java的类是代码的拷贝,而JS则用了原型链继承而已,所谓的构造函数只不过就是个普通函数,(只是大家习惯在使用时大写,这事也就成了规范)。
ES6的class本质上是构造函数的语法糖,只是这个语法糖写得更像是Java,为了做区分,我将在这篇博客上专门对比class和es5构造函数的不同写法
通过构造函数,我们能更了解JS的原型链设计原理,下面是构造函数的基本用法
function Person(name,age){ this.name=name this.age=age } const p=new Person('jack',23)
class Person{ constructor(name,age){ this.name=name this.age=age } } const p=new Person('jack',23)
Person.prototype={ constructor:Person, fn1(){}, fn2(){} }
class Person{ constructor(name,age){ ... }; fn1(){}; fn2(){}; }
function Person(name,age){ ... this.saiHi=function(){console.log(this.name)} }
class Person{ name=''; age=''; constructor(name,age){ ... }; fn1(){};//prototype上的 fn2(){}; sayHi=function(){console.log(this.name)} //自有的 }
构造函数的静态属性指的是构造函数自己能访问
Person.prop1='staticProp1' Person.prop2='staticProp2'
class Person{ static prop1='staticProp1' static prop2='staticProp2' constructor(name,age){ ... }; fn1(){};//prototype上的 fn2(){}; sayHi=function(){console.log(this.name)} //自有的 }
Person.staticFn=function (){}
class Person{ ... static staticFn=function(){} constructor(name,age){ ... }; ... }
function Person(name,age){ let _selfName='123456' //构造函数私有属性,无法被外部直接访问 let _selfFn=()=>{return _selfName} //构造函数私有方法,无法被外部直接访问 this.saiHi=function(){console.log(_selfFn())} //实例的自有方法 }
在变量名前加_,这种写法是开发者自己定义的,用来区分一下私有字段
class Person{ #selfName='123456' #selfFn=()=>{return this.#selfName} constructor(name,age){ ... }; sayHi=function(){console.log(this.#selfFn())}
class写法采用#关键字符来定义,如果想访问,需要加上this
this
由于私有字段无法直接访问,只好通过sayHi方法来变相访问了。
function Person(name,age){ let _selfName='123456' //构造函数私有属性,无法被外部直接访问 let _selfFn=()=>{return _selfName} //构造函数私有方法,无法被外部直接访问 this.name=name //实例的自有属性 this.age=age this.saiHi=function(){console.log(_selfFn())} //实例的自有方法 } Person.prototype={ //实例的共有方法 constructor:Person, fn1(){}, fn2(){} } Person.prop1='staticProp1' //构造函数的自有属性 Person.prop2='staticProp2' Person.staticFn=function (){} //构造函数的自有方法 const p=new Person('jack',23)
class Person{ name='';//这里也可以写实例的属性 age=''; static prop1='staticProp1'//构造函数的自有属性 static prop2='staticProp2' #selfName='123456'//构造函数私有属性,无法被外部直接访问 #selfFn=()=>{return this.#selfName}//构造函数私有方法,无法被外部直接访问 constructor(name,age){ this.name=name//实例的自有属性 this.age=age//实例的自有属性 }; fn1(){};//实例的共有方法 fn2(){};//实例的共有方法 sayHi=function(){console.log(this.#selfFn())}//构造函数的自有方法 } const p=new Person('jack',23)
采用构造函数方法可以分成两步实现。
第一步是在子类的构造函数中,调用父类的构造函数。
function Super(name){ this.name=name } function Sub(name,age){ Super.call(this,name) this.age=age }
上面代码中,Sub是子类的构造函数,this是子类的实例。在实例上调用父类的构造函数Super,就会让子类实例具有父类实例的属性。
第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型。
Super.prototype.sayHi=function (){console.log('hi')} Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub;//这句可加可不加,建议加
要注意不要直接Sub.prototype=Super.prototype,这样虽然也是有用的,但是就相当于两个构造函数共用一个原型,万一以后修改Sub或者Super其中一个的原型就会影响双方。
Sub.prototype=Super.prototype
最好的方法就是使用Object.Create直接改造子构造函数的原型,让子构造函数的__proto__连接到父构造函数的原型上。
Object.Create
__proto__
class Person{ name; age; constructor(name,age){ this.name=name this.age=age } sayHi(){ console.log(this.name) } } class Man extends Person{ constructor(name,age,prop){ super(name,age)//这里调用 this.prop=prop } } const a=new Man('qiuyanxi',20,'帅')
class的形式非常方便,目前子类已经能使用父类的方法了,而且无需再去关联子类和父类的原型链,extends关键字已经帮我们做好了工作
Man.prototype.__proto__===Person.prototype //true Man.__proto__ ===Person //true //注意,这是class自动实现的
class方法比ES5的方法多一种关系,ES5的方法并没有把子类的__proto__跟父类做关联,而class的写法则是自动做了关联。不过如果ES5想要实现的话也可以用Object.setPrototypeOf(Man,Person)关联
Object.setPrototypeOf(Man,Person)
//传统ES5继承手动挡 //原来 Sub.__proto__ ===> Function.protoyype Super.__proto__ ===> Function.protoyype //使用Object.setPrototypeOf(Sub,Super)后 Sub.__proto__ ===>Super===>Super.__proto__===>Function.prototype //使用Sub.prototype = Object.create(Super.prototype)后; Sub.prototype.__proto__ ===> Super.prototype
class的语法从未来来看,更多的新人朋友们可能会非常喜欢,这也非常符合学过JAVA的科班生,不过Js跟Java之间的差别还挺大的,还是建议能够在实践class的基础上,了解构造函数的工作原理,这能够帮助我们更好地理解Js这门不完美但是非常优秀的语言
https://wangdoc.com/javascript/oop/prototype.html
https://wangdoc.com/es6/class-extends.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
The text was updated successfully, but these errors were encountered:
No branches or pull requests
前言
JavaScript是没有类这个概念的,区别于其他传统的强类型语言,例如Java,JS的类(构造函数)在设计根本上就有本质的不同,Java的类是代码的拷贝,而JS则用了原型链继承而已,所谓的构造函数只不过就是个普通函数,(只是大家习惯在使用时大写,这事也就成了规范)。
ES6的class本质上是构造函数的语法糖,只是这个语法糖写得更像是Java,为了做区分,我将在这篇博客上专门对比class和es5构造函数的不同写法
设置实例对象自身属性
构造函数写法
通过构造函数,我们能更了解JS的原型链设计原理,下面是构造函数的基本用法
class写法
设置实例对象的共有方法
构造函数写法
class写法
设置实例对象的自有方法
构造函数写法
class写法
设置构造函数静态属性
构造函数的静态属性指的是构造函数自己能访问
构造函数写法
class写法
设置构造函数静态方法
构造函数写法
class写法
设置构造函数的私有字段
构造函数写法
在变量名前加_,这种写法是开发者自己定义的,用来区分一下私有字段
class写法
class写法采用#关键字符来定义,如果想访问,需要加上
this
由于私有字段无法直接访问,只好通过sayHi方法来变相访问了。
小结
构造函数写法
class写法
继承
构造函数写法
采用构造函数方法可以分成两步实现。
第一步是在子类的构造函数中,调用父类的构造函数。
上面代码中,Sub是子类的构造函数,this是子类的实例。在实例上调用父类的构造函数Super,就会让子类实例具有父类实例的属性。
第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型。
要注意不要直接
Sub.prototype=Super.prototype
,这样虽然也是有用的,但是就相当于两个构造函数共用一个原型,万一以后修改Sub或者Super其中一个的原型就会影响双方。最好的方法就是使用
Object.Create
直接改造子构造函数的原型,让子构造函数的__proto__
连接到父构造函数的原型上。class写法
class的形式非常方便,目前子类已经能使用父类的方法了,而且无需再去关联子类和父类的原型链,extends关键字已经帮我们做好了工作
class方法比ES5的方法多一种关系,ES5的方法并没有把子类的
__proto__
跟父类做关联,而class的写法则是自动做了关联。不过如果ES5想要实现的话也可以用Object.setPrototypeOf(Man,Person)
关联总结
class的语法从未来来看,更多的新人朋友们可能会非常喜欢,这也非常符合学过JAVA的科班生,不过Js跟Java之间的差别还挺大的,还是建议能够在实践class的基础上,了解构造函数的工作原理,这能够帮助我们更好地理解Js这门不完美但是非常优秀的语言
参考文档
https://wangdoc.com/javascript/oop/prototype.html
https://wangdoc.com/es6/class-extends.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
The text was updated successfully, but these errors were encountered: