面向对象;构造函数;原型对象

构造函数

1.什么是构造函数

定义:在js中,使用new关键字来调用的函数,被称为构造函数。

构造函数的作用:创建对象。

2.为什么要使用构造函数

假如需要创建多个类似的对象,我们会书写很多重复的无意义代码。此时我们使用构造函数,方便快捷的创建一个对象。

如何封装一个构造函数

将一个对象的特征作为属性,将它的行为作为方法。

function Dog(name,age,breed,color){
    this.name = name;
    this.age = age;
    this.breed = breed;
    this.color = color;
    this.show = function () {
    	alert("我只是一只小" + this.breed + "啊!")
    }
    this.bark = function () {
    	alert("汪汪汪!")
    }
}

【注意】构造函数的名字首字母大写。

3.构造函数的执行过程

function Animal(color){
	this.color = color;
}

当一个函数创建完成后,我们并不知道它是不是一个构造函数。像上面案例中,即使函数名首字母大写,我们也不确定它是构造函数。只有当一个函数前用new关键字来调用时,我们才能说它是一个构造函数。

var dog = new Animal("black")

构造函数的执行过程有以下4个步骤。

  1. 当用new关键字调用构造函数时,会开辟一个新的内存空间,这个内容空间就是新的对象实例。
  2. 将构造函数内部的this指向当前的内存空间(新的对象)。
  3. 执行函数内的代码。(对象的属性和方法的赋值。)
  4. 将内存空间的地址作为返回值返回。

4.构造函数的返回值

构造函数不需要手动添加返回值,默认返回新对象的内存地址。

(1)手动添加一个基础数据类型的返回值,最终还是返回新对象的内存地址。

function Person(name){
    this.name = name;
    return "蔡徐坤";
}
var p = new Person("范丞丞");
console.log(p.name);//范丞丞

(2)手动添加一个复合数据类型的返回值,返回手动添加的对象的内存地址。

function Person(name){
    this.name = name;
    return {name:"蔡徐坤"};
}
var p = new Person("范丞丞");
console.log(p.name);//蔡徐坤

5.与普通函数的区别

5.1调用方式的不同

普通函数使用函数名调用

构造函数通过new关键字来调用

5.2 返回值不同

普通函数的返回值是函数内return的结果

构造函数的返回值是函数内创建对象的地址。

5.3 作用的不同

构造函数时专门用来创建对象。

普通函数的作用可以自由定义。

原型对象

我们创建的每一个函数都有一个prototype属性,这个属性指向一个对象。而这个对象所有的属性和方法都会被构造函数拥有。

function Dog(name,age){
    this.name = name;
    this.age = age;
}
var dog1 = new Dog("来福",3)
var dog2 = new Dog("常威",2)
Dog.prototype.bark = function () {
    alert("汪汪汪!")
}
Dog.prototype.breed = "哈士奇";
alert(dog1.bark===dog2.bark);//true
alert(dog1.breed)//哈士奇
alert(dog2.breed)//哈士奇

对象的封装

一般情况下,公共属性定义到构造函数里面,公共的方法定义到原型对象身上。

混合模式(构造函数+原型 模式)

        function Dog(name,age,breed,color){
                this.name = name;
                this.age = age;
                this.breed = breed;
                this.color = color;
        }
        Dog.prototype.show = function () {
            alert("我只是一只小" + this.breed + "啊!")
        }
        Dog.prototype.bark = function () {
            alert("汪汪汪!")
        }

__proto__

每一个对象都有一个属性__proto__,这个属性指向构造函数的prototype,也就是构造函数的原型对象。我们之所以可以在对象中使用原型对象中的方法和属性就是因为对象中有__proto__属性的存在。

原型链

在这里插入图片描述

如果实例对象中调用了该对象没有的方法或属性,去__proto__去找方法或属性,如果还没有则继续往上寻找,直到null。

继承

面上对象的三大特性:封装(封装构造函数),继承,多态

ES6之前没有给我们提供 extends 继承。我们可以通过构造函数+原型对象的模式去模拟实现继承。这种方法也被称为组合继承。

function Dog(age){
    this.age = age;
}
Dog.prototype.bark = function(){
    alert("汪汪汪!")
}
function Huskie(name,age){
    this.name = name;
    this.age = age;
}
Huskie.prototype.bark = function(){
    alert("汪汪汪!")
}

像上面的案例中,哈士奇是属于狗的一种,如果我们重复定义了一样的属性和方法,写了一些重复的代码也造成了资源的浪费,所以我们让哈士奇继承狗的所有属性和方法。

使用call()方法实现继承

function Dog(age){
	this.age = age;
}
Dog.prototype.swimming = function(){
	alert("会游泳!")
}
function Huskie(name,age){
    Dog.call(this,age);
    this.name = name;
}
var hsq = new Huskie("二哈",2);
hsq.swimming();//报错 
特点:
  • 该方式是靠调用需要继承的构造函数来实现的,调用过程中使用call方法来改变this的指向。
  • call是不可以继承父对象原型中的属性和方法。
  • call是只能继承构造函数中的属性和方法。

优点:继承了父类构造函数中所有的属性和方法

缺点:不能继承父类原型对象中的属性和方法

使用prototype实现继承

在原型对象中有一个constructor属性,该属性指向该原型对象的构造函数。

function Dog(age){
            this.age = age;
        }
        Dog.prototype.bark = function(){
            alert("汪汪汪!")
        }
        function Huskie(name,age){
            this.name = name;
        }
        // 这样写相当于让子类与父类指向了同一个原型对象。如果修改了子类的原型对象,则父类的原型对象也会随之修改
        // Huskie.prototype = Dog.prototype;
        Huskie.prototype = new Dog(3);
        Huskie.prototype.constructor = Huskie;
        // var h = new Huskie("二哈");
        // console.log(h.age);
        // h.bark(); 
        // var dog = new Dog();
        // console.dir(dog)
        // console.dir(h.constructor === h.__proto__.constructor); true

优点:继承了父级原型上的属性和方法

缺点:实现化多个子类时,必须使用共同的属性值。

组合式继承

function Dog(age){
	this.age = age;
}
Dog.prototype.bark = function(){
	alert("汪汪汪!")
}
function Huskie(name,age){
    Dog.call(this,age);
    this.name = name;
}
//此时不需要给父类添加参数
Huskie.prototype = new Dog();
Huskie.prototype.constructor = Huskie;
var h = new Huskie("二哈",5);
console.log(h.age);
h.bark();

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值