class
2019-02-15 本文已影响0人
撑船的摆渡人
ES6引入class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。
class Person { //定义了一个名字为Person的类
constructor(name, age){ //constructor是一个构造方法,用来接收参数
this.name = name; //this代表的是实例对象
this.age = age;
}
say(){ //这是一个类的方法,注意千万不要加上function
return `我叫${this.name},${this.age}岁了`
}
}
let obj = new Person('andy',18);
console.log(obj.say());
类自身指向的就是构造函数,所以可以认为ES6中的类其实就是构造函数的另外一种写法。
console.log(typeof Person); //function
console.log(Person === Person.prototype.constructor); // true
实际上类的所有方法都定义在类的prototype属性上
class Person { //定义了一个名字为Person的类
constructor(name, age){ //constructor是一个构造方法,用来接收参数
this.name = name; //this代表的是实例对象
this.age = age;
}
say(){ //这是一个类的方法,注意千万不要加上function
return `我叫${this.name},${this.age}岁了`
}
}
Person.prototype.say = function(){ //定义与类中相同名字的方法。
return `覆盖类中的方法,我叫${this.name},${this.age}岁了`
}
let obj = new Person('andy',18);
console.log(obj.say());
也可以通过prototype属性对类添加方法
Person.prototype.addFn=function(){
return "我是通过prototype新增加的方法addFn";
}
let obj = new Person('andy',18);
console.log(obj.addFn());
还可以通过Object.assign方法来为对象动态添加方法
Object.assign(Person.prototype,{
getName:function(){
return this.name;
},
getAge:function(){
return this.age;
}
})
let obj = new Person('andy',18);
console.log(obj.getName());
console.log(obj.getAge());
constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。
class Box {
constructor(){
console.log('实例化对象时,自动调用')
}
}
let obj2 = new Box();
constructor方法如果没有显示定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。
class Desk {
constructor(){
this.haha = '你好'
}
}
class Body {
constructor(){
return new Desk();// 没有用this,直接返回一个全新的对象
}
}
let obj3 = new Body();
console.log(obj3.haha);
constructor中定义的属性可以称为实例属性(既定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(既定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值,true说明是实例属性,false说不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
class Box{
constructor(num1,num2){
this.num1 = num1;
this.num2 = num2;
}
sum(){
return num1 + num2;
}
}
let box = new Box(12,88);
console.log(box.hasOwnProperty('num1'));
console.log(box.hasOwnProperty('num2'));
console.log(box.hasOwnProperty('sum'));
console.log('num1' in box);
console.log('num2' in box);
console.log('sum' in box);
console.log('say' in box);
类的所有实例共享一个原型对象,他们的原型都是Person.prototype,所以proto属性时相等的
class Person{
constructor(m,n){
this.m = m;
this.n = n;
}
sum(){
return m + n;
}
}
p1与p2都是Person的实例,它们的proto都指向Person的prototype
let p1 = new Person(1,2);
let p2 = new Person(4,8);
console.log(p1.__proto__,p1.__proto__ === p2.__proto__);
由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!
p1.__proto__.sub = function(){
return this.n - this.m
}
console.log(p1.sub());
console.log(p2.sub());
class不存在变量提升,所以需要先定义在使用。因为ES6不会把类的声明提升到代码头部,但是ES5存在变量提升,可以先使用,然后在定义。
ES5可以先使用在定义,存在变量提升
new A();
function A(){
console.log('ES5执行了')
}
ES6不能使用在定义,不存在变量提升,会报错
new B();
class B{
constructor(){
console.log('ES6执行时保错,B is not defined')
}
}