js面向对象编程

创建对象

创建方法

  • new
let a = new Object();
a.name = "xiaoming";
console.log(a); // => {name: 'xiaoming'}
  • {}
let b = {};
b.name = "dong";
console.log(b); // => { name: 'dong' }

创建模式

本质上只有上面两种方式创造对象,但是如果创建很多相同的对象用这种方法的话,会产生很多重复代码,所以需要有别的模式来创造很多对象。

let p1 = new Object();
p1.name = 'xiaohong';
p1.say = function(){
    console.log("I am " + this.name);
}

p1.say();

当你需要创建很多个结构一样的对象都要这样复制一遍,那就太蛋疼了。所以去掉这些重复的代码就用到了工厂模式。

工厂模式

function createPerson(name){
    let o = new Object();
    o.name = name;
    o.say = function(){
        console.log("I am " + o.name);
    }

    return o;
}

let p1 = createPerson('xiaohong');
p1.say();

let p2 = createPerson('ming');
p2.say();

/*
I am xiaohong
I am ming
*/

这样改了之后创建对象就简单很多了,基本实现了代码复用。但是有个缺陷就是没办法识别不同类型的对象,只知道是Object对象。

构造函数模式
function Person(name){
    this.name = name;
    this.say = function(){
        console.log("I am " + this.name);
    }

    /** 和上面函数逻辑是一样的
     * this.say = new Function("console.log("I am " + this.name)")
     */
}

let p1 = new Person('hong');
p1.say();

let p2 = new Person('ming');
p2.say();

console.log(p1 instanceof Person);
console.log(p1.say == p2.say);

/*
I am hong
I am ming
true
false
*/

使用构造函数已经可以识别对象的类型了,每创建一个对象,属性和方法都会复制一份,对于属性每个对象都有一份挺正常的,但是没必要需要多份完成一样任务的方法。

原型模式

每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。 既该构造函数的所有实例共享prototype里的内容。每创建一个函数,就会同时创建它的 prototype 对象,这个对象也会自动获得 constructor 属性

function Person(){

}
Person.prototype.name = 'hua';
Person.prototype.friends = ['gang', 'li'];
Person.prototype.say = function(){
    console.log("I am " + this.name + " friends:" + this.friends);
}

let p1 = new Person();
p1.name = 'ming';
p1.friends.push('qiang');

let p2 = new Person();
p2.name = 'hong';
p2.friends.push('chen');

p1.say();
p2.say();
console.log(p1.say == p2.say);

/*
I am ming friends:gang,li,qiang,chen
I am hong friends:gang,li,qiang,chen
true
*/

p1和p2都有一个 __proto__指向了Person的 prototype 对象,原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属性。然而,对于包含引用类型值的属性来说,问题就比较突出了。

组合使用构造函数模式和原型模式
function Person(name){
    this.name = name;
    this.friends = ['gang', 'li'];
}

Person.prototype.say = function(){
    console.log("I am " + this.name + " friends:" + this.friends);
}

let p1 = new Person('hong');
p1.friends.push('qiang');

let p2 = new Person('ming');
p2.friends.push('chen');

p1.say();
p2.say();

/*
I am hong friends:gang,li,qiang
I am ming friends:gang,li,chen
*/

这样创建出来的每个对象都是独享属性,共享方法了。

继承

这个时候如果我想新创建一种对象Student,这个对象有Person所有的属性和方法,另外还有属于Student的新属性和方法,那么我要把Person的内容再复制一遍吗?这样明显没有做到代码复用,这个时候就要用到了prototype来实现继承了。

原型链

借用构造函数

组合继承

寄生组合式继承

class继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值