资讯专栏INFORMATION COLUMN

JS构造函数内的方法与构造函数prototype属性上方法的对比

SmallBoyO / 1202人阅读

摘要:本文的目的是让大家理解什么情况下把函数的方法写在的构造函数上什么时候把方法写在函数的属性上以及这样做的好处为了阅读方便我们约定一下把方法写在构造函数内的情况我们简称为函数内方法把方法写在属性上的情况我们简称为上的方法首先我们先了解一下这篇文

本文的目的是让大家理解什么情况下把函数的方法写在JavaScript的构造函数上,什么时候把方法写在函数的prototype属性上;以及这样做的好处.

为了阅读方便,我们约定一下:把方法写在构造函数内的情况我们简称为函数内方法,把方法写在prototype属性上的情况我们简称为prototype上的方法

首先我们先了解一下这篇文章的重点:

函数内的方法: 使用函数内的方法我们可以访问到函数内部的私有变量,如果我们通过构造函数new出来的对象需要我们操作构造函数内部的私有变量的话,
我们这个时候就要考虑使用函数内的方法.

prototype上的方法: 当我们需要通过一个函数创建大量的对象,并且这些对象还都有许多的方法的时候;这时我们就要考虑在函数的prototype上添加这些方法.
这种情况下我们代码的内存占用就比较小.

在实际的应用中,这两种方法往往是结合使用的;所以我们要首先了解我们需要的是什么,然后再去选择如何使用.

我们还是根据下面的代码来说明一下这些要点吧,下面是代码部分:

// 构造函数A
function A(name) {
    this.name = name || "a";
    this.sayHello = function() {
        console.log("Hello, my name is: " + this.name);
    }
}

// 构造函数B
function B(name) {
    this.name = name || "b";
}
B.prototype.sayHello = function() {
    console.log("Hello, my name is: " + this.name);
};

var a1 = new A("a1");
var a2 = new A("a2");
a1.sayHello();
a2.sayHello();

var b1 = new B("b1");
var b2 = new B("b2");
b1.sayHello();
b2.sayHello();

我们首先写了两个构造函数,第一个是A,这个构造函数里面包含了一个方法sayHello;第二个是构造函数B,我们把那个方法sayHello写在了构造函数Bprototype属性上面.

需要指出的是,通过这两个构造函数new出来的对象具有一样的属性和方法,但是它们的区别我们可以通过下面的一个图来说明:

我们通过使用构造函数A创建了两个对象,分别是a1,a2;通过构造函数B创建了两个对象b1,b2;我们可以发现b1,b2这两个对象的那个sayHello方法都是指向了它们的构造函数的prototype属性的sayHello方法.而a1,a2都是在自己内部定义了这个方法.

定义在构造函数内部的方法,会在它的每一个实例上都克隆这个方法;定义在构造函数的prototype属性上的方法会让它的所有示例都共享这个方法,但是不会在每个实例的内部重新定义这个方法.如果我们的应用需要创建很多新的对象,并且这些对象还有许多的方法,为了节省内存,我们建议把这些方法都定义在构造函数的prototype属性上当然,在某些情况下,我们需要将某些方法定义在构造函数中,这种情况一般是因为我们需要访问构造函数内部的私有变量.

下面我们举一个两者结合的例子,代码如下:

function Person(name, family) {
    this.name = name;
    this.family = family;
    
    var records = [{type: "in", amount: 0}];

    this.addTransaction = function(trans) {
        if(trans.hasOwnProperty("type") && trans.hasOwnProperty("amount")) {
           records.push(trans);
        }
    }

    this.balance = function() {
       var total = 0;

       records.forEach(function(record) {
           if(record.type === "in") {
             total += record.amount;
           }
           else {
             total -= record.amount;
           }
       });
    
        return total;
    };
};

Person.prototype.getFull = function() {
    return this.name + " " + this.family;
};

Person.prototype.getProfile = function() {
     return this.getFull() + ", total balance: " + this.balance();
};

在上面的代码中,我们定义了一个Person构造函数;这个函数有一个内部的私有变量records,这个变量我们是不希望通过函数内部以外的方法去操作这个变量,所以我们把操作这个变量的方法都写在了函数的内部.而把一些可以公开的方法写在了Personprototype属性上,比如方法getFullgetProfile.

把方法写在构造函数的内部,增加了通过构造函数初始化一个对象的成本,把方法写在prototype属性上就有效的减少了这种成本.你也许会觉得,调用对象上的方法要比调用它的原型链上的方法快得多,其实并不是这样的,如果你的那个对象上面不是有很多的原型的话,它们的速度其实是差不多的。

另外,需要注意的一些地方:

首先如果是在函数的prototype属性上定义方法的话,要牢记一点,如果你改变某个方法,那么由这个构造函数产生的所有对象的那个方法都会被改变.

还有一点就是变量提升的问题,我们可以稍微的看一下下面的代码:

func1(); // 这里会报错,因为在函数执行的时候,func1还没有被赋值. error: func1 is not a function
var func1 = function() {
    console.log("func1");
};

func2(); // 这个会被正确执行,因为函数的声明会被提升.
function func2() {
    console.log("func2");
}

关于对象序列化的问题.定义在函数的prototype上的属性不会被序列化,可以看下面的代码:

function A(name) {
    this.name = name;
}
A.prototype.sayWhat = "say what...";

var a = new A("dreamapple");
console.log(JSON.stringify(a));

我们可以看到输出结果是{"name":"dreamapple"}

原文地址:github

参考的文章或者问答:

Methods Within Constructor vs Prototype in Javascript

Use of "prototype" vs. "this" in JavaScript?

Advantages of using prototype, vs defining methods straight in the constructor? [duplicate]

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/79701.html

相关文章

  • 构造函数方法构造函数prototype属性方法对比

    摘要:挺有用的一篇文章,今天还有人在问我关于构造函数的方法和原型,构造函数的方法是定义在函数内容,作为一个私有方法,不对外开放,而则可以通过对象定义,在外面访问,更加深入请看本文。 挺有用的一篇文章,今天还有人在问我关于构造函数的方法和原型,构造函数的方法是定义在函数内容,作为一个私有方法,不对外开放,而prototype则可以通过对象定义,在外面访问,更加深入请看本文。 本文的目的是让大家...

    Eidesen 评论0 收藏0
  • 复习笔记(新手向) - JS对象声明几种方式

    摘要:二用操作符构造对象属性名属性值属性名属性值属性名属性值属性名属性值方法名方法名首先用创建一个空对象,然后用多条语句给对象添加属性方法。他的写法与三用函数声明的方式构造对象比较像,但是稍有不同。 -- 新手向知识,就不用ES6写法了。 一、字面量声明 var obj = { 属性名1 : 属性值, 属性名2 : 属性值, 属性名3 : 属性...

    davidac 评论0 收藏0
  • 浅谈 JS 创建对象 8 种模式

    摘要:模式工厂模式构造器模式通过对象实现模式构造器与原型方式的混合模式动态原型模式混合工厂模式模式字面量的表现形式等价于即以对象为一个原型模板新建一个以这个原型模板为原型的对象区别创建一个原型为的对象在里查看各个新建对象的区别可以看出前种模式创建 Objct 模式 工厂模式 构造器模式 通过 Function 对象实现 prototype 模式 构造器与原型方式的混合模式 动态原型模式 混...

    caoym 评论0 收藏0
  • Class:向传统类模式转变构造函数

    摘要:所以的类等同于构造函数。只能存在于子类的构造方法中,这时它指代父类构造函数。指代父类的构造函数此时指向,打印出。改变了构造函数的行为,一旦发现其不是通过这种形式调用的,构造函数会忽略传入的参数。 前言 JS基于原型的‘类’,一直被转行前端的码僚们大呼惊奇,但接近传统模式使用class关键字定义的出现,却使得一些前端同行深感遗憾而纷纷留言:还我独特的JS、净搞些没实质的东西、自己没有类还...

    jone5679 评论0 收藏0
  • JS函数(1)

    摘要:前言这段时间突然发现原生好多东西都忘记了但有些东西确实很重要所以又重新再梳理一次。 showImg(https://segmentfault.com/img/bVbqqkr?w=874&h=382); 前言 这段时间突然发现JS原生好多东西都忘记了,但有些东西确实很重要,所以又重新再梳理一次。主要有函数的3种定义方法,ES5函数this指向,call与appl用法,JS常见的4种设计模...

    宋华 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<