javascript创建对象及继承方式

创建对象

1.字面量

var people = {
    age: 20,
    name: '小张',
    setName: function (name) {
        this.name = name;
    }
}
//使用方式
console.log(people.name)
people.setName("小赵")

适用于创建初始数据确定的对象,但是当创建多个对象时,代码重复率过高。


2.工厂模式

function createPeople(name, age) {
    var obj = {
        name,
        age,
        setName: function (name) {
            this.name = name;
        }
    }
    return obj
}
//使用方式
var p1 = createPeople('小张', 20)
var p2 = createPeople('小赵', 20)

解决了创建多个对象代码重复率过高的问题,但是由此创建的对象无具体类型,都是Object类型


 3.构造函数

//Object构造函数模式
var people = new Object();
people.name = "小张";
people.age = 20;
people.setName = function (name) {
    this.name = name;
}
//使用方式
console.log(people.name);
people.setName('小赵');

适用于起始不确定对象里面的内容时,但是语句较多。

//自定义构造函数
function People(name, age) {
    this.name = name;
    this.age = age;
    this.setName = function (name) {
        this.name = name;
    }
}
//使用方式
var p1 = new People('小张', 20);
p1.setName('小赵');

解决了创建对象无具体类型的问题,但是创建多个对象会浪费内存。

(创建了多个函数对象setName(),就开辟了多个空间,虽然对象指向不同地址,但是地址内容都是重复的,造成内存浪费)


 4.原型

function People() {}
People.prototype = {
    constructor: People,
    name: '小张',
    age: 20,
    setName: function (name) {
        this.name = name;
    }
}
//使用
var p = new People()
p.constructor.prototype.name = '小赵'

解决了自定义构造函数中函数对象复用的问题,但是一个实例对原型属性的修改会影响到其它实例


 5.组合模式(原型+构造)

function People(name, age) {
    this.name = name;
    this.age = age;
}
People.prototype.setName = function (name) {
    this.name = name;
}
//使用
var p = new People('小张', 20)
p.setName('小赵')

解决了各自的缺点,构造函数初始化对象属性,原型实现函数方法的复用,但是代码封装性不好


 6.动态原型

function People(name, age) {
    this.name = name;
    this.age = age;
    if (typeof this.setName !== 'function') {
        People.prototype.setName = function (name) {
            this.name = name;
        }
    }
}

解决了组合模式封装性差的问题

7.寄生构造模式

 function People(name, age) {
    var obj = {
        name,
        age,
        setName: function (name) {
            this.name = name;
        }
    }
    return obj
}
//使用方式
var p1 = new People('小张', 20)
var p2 = new People('小赵', 20)

除了使用方式与工厂模式不同,其它一样


继承方式

1.原型链

function People(name) {
    this.name = name;
}
People.prototype.addAge = function (age) {
    this.age = age;
}
function Student(name, grade) {
    this.grade = grade;
}
Student.prototype = new People();   // 子类型的原型为父类型的一个实例对象
Student.prototype.constructor = Student;  // 让子类型的原型的constructor指向子类型
var xiaoZhang = new Student('小张', 60);  
xiaoZhang.addAge(20);

 缺点:包含引用类型时,会被所有实例共享,改动将影响所有实例,且不能向父类传递参数。


2.构造函数

function People(name) {
    this.name = name;
    this.setName = function (name) {
        this.name = name;
    }
}
People.prototype.addAge = function (age) {
    this.age = age;
}
function Student(name, grade) {
    People.call(this, name);
    this.grade = grade;
}
var xiaoZhang = new Student('小张', 60);
xiaoZhang.setName('小赵')
// xiaoZhang.addAge(20)    //报错

解决了不能向父类传递参数缺点,但是跟创建对象中构造函数模式问题一样,无法实现函数方法复用,并且父类原型上的方法对子类不可见。


3.组合模式(原型链+构造)

function People(name) {
    this.name = name;
}
People.prototype.addAge = function (age) {
    this.age = age;
}
function Student(name, grade) {
    People.call(this, name);     //第一次调用
    this.grade = grade;
}
Student.prototype = new People();  //第二次调用
Student.prototype.constructor = Student;
var xiaoZhang = new Student('小张', 60);
xiaoZhang.addAge(20);

 组合模式解决了两者单独使用的缺点,但是缺点是调用了两次父类的构造函数。 


4.原型式继承

function People(obj) {
    function Student() {
        this.name = obj.name;
        this.setName = function (name) {    //无法被复用的函数,练习使用
            this.name = name;
        }
    }
    Student.prototype = obj;
    return new Student();
}
var student = {
    name: '小张',
    addAge: function (age) {
        this.age = age;
    }
}
var new_student = People(student)
new_student.addAge(20);
new_student.setName('小赵');

 原型式继承只是对某个对象实现一种简单继承,缺点同原型链继承。


5.寄生式继承(原型式+工厂)

function People(obj) {
    function Student() {
        this.name = obj.name;
        this.setName = function (name) {
            this.name = name;
        }
    }
    Student.prototype = obj;
    return new Student();
}
 function createStudent(obj){
     var clone = People(obj);
     clone.addAge = function(age){   //扩展对象,但无法实现复用
         this.age = age;
     }
     return clone;
 }
 var student = {
     name:'小张',
 }
var new_student = createStudent(student);
new_student.addAge(20);
new_student.setName('小赵');

优点:可以为对象进行扩展。缺点:同原型式继承一样,且扩展函数无复用。


6.寄生式组合继承

function People(name) {
    this.name = name;
}
People.prototype.addAge = function (age) {
    this.age = age;
}
function Student(name, grade) {
    People.call(this, name);     //仅一次调用
    this.grade = grade;
}
Student.prototype = Object.create(People.prototype);   //关键的一行
Student.prototype.constructor = Student;
var xiaoZhang = new Student('小张', 60);
xiaoZhang.addAge(20);

使用父类原型的副本作为子类原型,避免了调用了两次父类的构造函数。

如有不正,请批评指正......

试着自己写一遍后发现,我真的会谢。。。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值