JavaScript-基础02-类和继承

类创建方法

Javascript是一种基于对象的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有Class。在JS中创建类的几种方式:

1. 工厂方式

//通过工厂方式创建对象,先定义一个工厂方法
function createObj(){
    var obj  =  new Object();
    obj.name="xxx";
    obj.say=function(){
        alert("我是xxx");
    }
    return obj;
}
//调用工厂方法创建对象:
var obj1  =  createObj();

这种方式的问题是每一次通过工厂方法去创建一个对象,这个对象的属性name和方法say都必须重新创建一次,浪费内存。

2. 构造器方式

//创建一个构造器,构造函数首字母大写
function Obj(){
    this.name="xxx";
    this.say=function(){
        alert("我是xxx");
    };
}
//利用构造器,通过new关键字生成对象
var obj1=new Obj();

这是最基本的方式,但是创建一个对象,这个对象的属性name和方法say都必须重新创建一次,浪费内存。

3. 原型方式

//用空函数创建一个类
function Obj(){
}
//在类的原型链上添加属性和方法
Obj.prototype.name="xxx";
Obj.prototype.say=function(){
    alert("我是xxx");
}
//生成对象
var obj1=new Obj();

这个方式的缺点是,当有引用属性时,改变一个对象的这个属性也会改变其他对象的这个属性。因为一个引用属性,都是指向的同一个地方。

4. 原型/构造联合方式

//用构造函数定义对象的非函数属性
function Obj(name){
    this.name=name;
    this.arr=new Array('a','b');
}
//用原型方式定义对象的方法
Obj.prototype.say=function(){
    alert("我是xxx");
}
//生成对象
var obj1 = new Obj('xxx');

这种是目前用的最多的创建类和对象的方式,将方法和属性用不同的方式封装。

5. 动态原型方式

//动态原型方式和原型/构造混合方式的原理相似,唯一的区别就是赋予对象方法的位置
function Person(name, sex) {
    this.name = name;
    this.sex = sex;
    if (typeof this.say != "function") {
        Person.prototype.say = function () {
            alert(this.name);
        }
    }
}
var man =new Person ("wwm", "男");
man.say();

动态原型模式是将所有的信息都封装到构造函数中,构造函数中,只用say不存在的情况下,才会将它添加到原型中。这段代码只有在初次调用时才会执行。

6. 利用Object.create()方法构造

User={
		name:'hello',
		getName:function(){
			return this.name;
		}
}

//使用
var user=Object.create(User);
alert(user.getName());

实例化obj对象有三步:

  1. 创建obj对象:obj=new Object();
  2. 将obj的内部__proto__指向构造他的函数Obj的prototype
  3. 将obj作为this去调用构造函数Obj,从而设置成员(即对象属性和对象方法)并初始化。
    在这里插入图片描述

类的继承

1.原型链继承

将父类的实例作为子类的原型

  // 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};


function Cat(){ 
}


// Cat的原型对象指向Animal的实例对象
Cat.prototype = new Animal();

//手动改constructor指回原来的构造函数
// Cat.prototype.constructor = Cat  
Cat.prototype.name = 'newcat';

// Test Code
var cat = new Cat();
console.log(cat);

在这里插入图片描述

特点:

非常纯粹的继承关系,实例是子类的实例,也是父类的实例 父类新增原型方法/原型属性,
子类都能访问到
简单,易于实现

缺点:

要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行, 无法实现多继承
来自原型对象的所有属性被所有实例共享
创建子类实例时,无法向父类构造函数传参

构造函数继承

通过call()把父类型的this指向子类型的this,这样就可以实现子类型继承父类型的属性。

// 借用父构造函数继承属性
//父构造函数
function Father (uname, age) {
  //this指向父构造函数的对象实例
	this.uname = uname
  this.age = age
  this.say = function(){
    console.log('father定义的');
  }
}
// 子构造函数
function Son (uname, age){
  // this指向子构造函数的对象实例
  //借助于call,this指向子构造函数对象实例
  Father.call(this, uname, age)
  
}
var son = new Son('wwm',18)
// 子类有父类所有的属性和方法
console.log(son) //
console.log(son.uname);
console.log(son.age);
son.say();

在这里插入图片描述

组合继承(构造函数和原型法)

通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用

// 父构造函数
function Father (uname, age) {
  //this指向父构造函数的对象实例
	this.uname = uname
  this.age = age
  this.say = function(){
    console.log('父类定义');
  }
}
// 父原型方法
Father.prototype.money = function() {
	console.log(10000)
}
// 子构造函数
function Son (uname, age){
  // this指向子构造函数的对象实例
  //借助于call,this指向子构造函数对象实例
  Father.call(this, uname, age)
  
}

// Son.prototype = Father.prototype 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会变化/
Son.prototype = new Father()

//手动改constructor指回原来的构造函数
Son.prototype.constructor = Son  
Son.prototype.exam= function() {
 console.log('考试')
}

var son = new Son('wwm',18)
// 子类有父类所有的属性和方法
console.log(son) //
console.log(son.uname);
son.exam();
console.log(son.age);
son.say();

在这里插入图片描述
在这里插入图片描述

内容仅供学习参考,若有错误欢迎大家指正----WUCASE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值