欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JS构造函数的出现必要及原型(prototype)属性使用的必要

程序员文章站 2022-03-22 11:05:10
JS构造函数的出现必要及原型(prototype)属性使用的必要首先通过一系列代码改写来观察构造函数及原型属性的使用必要性与重要性:初代代码:let obj1 = { name: 'Jack', myRun: function () { console.log('我是' + this.name + '我会跑'); }}let obj2 = { name: 'Rose', myRun: function () { consol...

JS构造函数使用的必要及原型(prototype)属性使用的必要性

首先通过一系列代码的改写,来观察构造函数及原型属性的使用的必要性与重要性:

初代代码:

let obj1 = {
    name: 'Jack',
    myRun: function () {
        console.log('我是' + this.name + '我会跑');
    }
}

let obj2 = {
    name: 'Rose',
    myRun: function () {
        console.log('我是' + this.name + '我会跑');
    }
}

obj1.myRun();
obj2.myRun();

这段代码中,主要有两大问题:

问题一:每当new一个新对象,都要重新写一遍对象的结构,不灵活
问题二:在这段代码中,浪费内存资源的部分最主要的是对象里myRun函数的声明
因为每当new一个对象时,都要在堆内存中开辟一个存放此对象的内存。而在这个例子中,这段堆内存主要存放name与myRun() 两个数据。显然,name属性是必要的,用来区分每个不同对象类似于id;但是myRun()方法是可以用调用来节省空间的,也就是说只用声明一次即可,不需要每次都跟着新对象开辟一段新空间;

二代代码(解决初代代码问题一):

function person(name) { // 工厂函数,
    this.name = name;
    this.myRun = function () {
        console.log('我是' + this.name + '我会跑');
    }
}
let person1 = new person('Jack');
person1.myRun();
let person2 = new person('Rose');
person2.myRun();

这段代码中,使用了工厂函数来构造同一类对象的模板,而每次new一个obj时都可以通过这段模板来新建对象,代码复用率更高;

这段工厂函数也就是JS中所谓的构造函数,使用十分方便,通过一个function就可以创造多个对象,这里应该是JS“一切皆对象”思想;不像java 、c++这些面向对象语言,构造函数和对象使用十分繁琐

三代代码(解决初代代码问题二):

let run = function () {
    console.log('我是' + this.name + '我会跑');
}

let obj1 = {
    name: 'Jack',
    myRun: run
};

let obj2 = {
    name: 'Rose',
    myRun: run
}

obj1.myRun();
obj2.myRun();

此段代码中,run()方法只构造声明了一次,在堆内存中存放着。虽然,每new一次新的obj,都赋值了一次myRun属性,但是只是把run()方法在堆内存中的地址赋值给了每一个对象的myRun属性。所以,这个过程类似于变量赋值和引用,大大节省了内存空间相比于初代代码。

四代代码(在构造函数的基础上用原型(prototype/__ proto __)构造对象自身方法)

person.prototype.myRun = function run() {
    console.log('我是' + this.name + '我会跑');
}

function person(name) {
    this.name = name;
}
let person1 = new person('Jack');
person1.myRun();
let person2 = new person('Rose');
person2.myRun();
console.log(person2)

这段代码在内存空间效率上和三代代码差不多,但是复用率更高,因为原型的应用即是给模板对象(祖宗)构造myRun()方法,而每一个用此模板(祖宗)new的新对象(person1,person2)都会继承此方法;

现象:打印person1,person2不会有myRun()方法:

JS构造函数的出现必要及原型(prototype)属性使用的必要

因为存在于__ proto __中:

JS构造函数的出现必要及原型(prototype)属性使用的必要

也就是说和三代代码同理,不会为myRun开辟新内存空间。只在栈内存中调用原型中myRun()方法的堆内存地址;

(在这里Person(对象模板).prototype === person1(对象实例).__ proto __)

本文地址:https://blog.csdn.net/Sang_S_H/article/details/110196043