注册 登录

清河洛

javascript中面向对象中的创建对象

qingheluo2016-12-16清河洛470
面向对象语言的一个标志就是类的概念,通过类可以创建任意多个具有相同属性和方法的对象但是在ES6之前,javascript中没有类的概念,当时JS的面向对象是“非正统”且怪异的使用构造函数(构造方法)用来创建对象在函数中使用this关键字来指向将要创建的对象,并且没有return语句function Box(name, age) { this.name = name; this.run = function () { return this.name + "运行中..."; }; } Box.prototype.sleep = f...

面向对象语言的一个标志就是的概念,通过类可以创建任意多个具有相同属性和方法的对象

但是在ES6之前,javascript中没有类的概念,当时JS的面向对象是“非正统”且怪异的

使用构造函数(构造方法)用来创建对象

在函数中使用this关键字来指向将要创建的对象,并且没有return语句

function Box(name, age) {
    this.name = name;
    this.run = function () {
        return this.name + "运行中...";
    };
}
Box.prototype.sleep = function () {
  return this.name + "睡觉中...";
};
    // 通过原型添加方法或属性
var box1 = new Box('Lee');
var box2 = new Box('Jack');

构造函数也是函数,但必须使用new运算符,这是构造函数和普通函数的唯一区别

ES6中的类

在ES6中引入了的概念作为对象的模板,通过class关键字定义类

在class代码块中,所有的方法不需要写function关键字,直接编写函数定义就可以了,方法与方法不要逗号分隔,加了会报错

一个类中必须有构造函数,如果没有显示编写,则会自动添加一个空的构造函数:constructor(){}

class Box{
    constructor(name){
        this.name = name;
        this.run = function () {
            return this.name + "运行中...";
        };
    }
    sleep() {
        return this.name + "睡觉中...";
    }
}

run方法是Box本身的方法
sleep方法是定义在Box原型上的方法,相当于
    Box.prototype.sleep = function () {
        return this.name + "睡觉中...";
    };

ES6中的类实质上就是一个函数,指向的就是构造方法

class Box{...}

typeof Box;   // "function"
Box === Box.prototype.constructor  // true

所以ES6的class可以看作只是一个语法糖,其本质还是通过ES5中的构造函数来创建对象,新的写法只是让代码更加清晰、更像面向对象编程的语法而已

对象自身的可枚举的属性和方法是在constructor()构造方法中使用this关键字定义的,其余位置定义的方法都是定义在类的原型上,是不可枚举的

在class代码块中,允许在最顶层直接定义自身可枚举属性而无需写在构造函数中,且不需要this和 let/const/var 关键字

class Box{
    name = "qian";
    age = 33;
    sleep() {
        return this.name + "睡觉中...";
    }
}

这种写法的好处是所有实例对象自身的属性都定义在类的头部,看上去比较整齐,清晰

取值函数(getter)和存值函数(setter)

在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为

class Box{
    name = "qian";
    age = 33;
    get name() {
        return this.name + "is good man";
    }
    set name(new_val) {
        this.name = new_val + "is bad man";
    }
}

动态属性名和方法名

使用中括号包含变量名可以动态定义属性名或方法名

let demo = "sleep";
class Box{
    name = "qian";
    [demo](){
        return this.name + " sleeping...";
    }
}
let box = new();
console.log(box.sleep())
demo = "run"
console.log(box.run())

当变量demo的值改变时,Box的方法名也会跟着改变

class表达式

与函数一样,类也可以使用表达式的形式定义

const Box = class {...}

静态方法和属性

类相当于实例的原型,所有在类中定义的方法,都会被实例继承

如果在一个方法或属性前加上static关键字,就表示不会被实例继承,而是直接通过类来调用

class Box{
    static name = "qian";
    static run(){
        console.log(this.name + "running...");
    }
}
let box = new Box();
box.run();  // 报错,因为实例没有继承该方法
Box.run();  // 正常运行

要注意,静态方法中的this关键字指向的是类本身,而不是实例

私有方法和属性

在属性和方法名前面加上井号(#)前缀表示为私有,仅在当前class代码块中可以访问,其他任何地方都无法访问

class Box{
    #name = "qian";
    #run(){
        console.log(this.#name + "running...");
    }
        // 获取或修改时同样需要加井号(#)前缀
    static #sleep(){}
        // 静态方法或属性也可以设置为私有
}

当获取一个不存在的静态属性时会报错,而不是向正常属性时返回undefined

in运算符用来判断私有属性或方法是否存在

in运算符只能用在类的内部

class Box{
    #name = "qian";
    static run(){
        console.log(#name in this);
    }
}


网址导航