0
点赞
收藏
分享

微信扫一扫

javascript创建对象及继承方式

洒在心头的阳光 2022-04-23 阅读 89
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);

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

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

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

举报

相关推荐

0 条评论