`

JavaScript Garden - 构造函数

阅读更多

构造函数

JavaScript 中的构造函数和其它语言中的构造函数是不同的。
通过 new 关键字方式调用的函数都被认为是构造函数。

在构造函数内部 - 也就是被调用的函数内 - this 指向新创建的对象 Object
这个新创建的对象的 prototype 被指向到构造函数的 prototype

如果被调用的函数没有显式的 return 表达式,则隐式的会返回 this 对象 - 也就是新创建的对象。

function Foo() {
    this.bla = 1;
}

Foo.prototype.test = function() {
    console.log(this.bla);
};

var test = new Foo();

上面代码把 Foo 作为构造函数调用,并设置新创建对象的 prototype 为 Foo.prototype

显式的 return 表达式将会影响返回结果,但仅限于返回的是一个对象。

function Bar() {
    return 2;
}
new Bar(); // 返回新创建的对象

function Test() {
    this.value = 2;

    return {
        foo: 1
    };
}
new Test(); // 返回的对象

译者注new Bar() 返回的是新创建的对象,而不是数字的字面值 2。
因此 new Bar().constructor === Bar,但是如果返回的是数字对象,结果就不同了,如下所示

function Bar() {
    return new Number(2);
}
new Bar().constructor === Number

译者注这里得到的 new Test()是函数返回的对象,而不是通过new关键字新创建的对象,因此:

(new Test()).value === undefined
(new Test()).foo === 1

如果 new 被遗漏了,则函数不会返回新创建的对象。

function Foo() {
    this.bla = 1; // 获取设置全局参数
}
Foo(); // undefined

虽然上例在有些情况下也能正常运行,但是由于 JavaScript 中 this 的工作原理,
这里的 this 指向全局对象

工厂模式

为了不使用 new 关键字,构造函数必须显式的返回一个值。

function Bar() {
    var value = 1;
    return {
        method: function() {
            return value;
        }
    }
}
Bar.prototype = {
    foo: function() {}
};

new Bar();
Bar();

上面两种对 Bar 函数的调用返回的值完全相同,一个新创建的拥有 method 属性的对象被返回,
其实这里创建了一个闭包

还需要注意, new Bar() 并不会改变返回对象的原型(译者注也就是返回对象的原型不会指向 Bar.prototype)。
因为构造函数的原型会被指向到刚刚创建的新对象,而这里的 Bar 没有把这个新对象返回(译者注:而是返回了一个包含 method 属性的自定义对象)。

在上面的例子中,使用或者不使用 new 关键字没有功能性的区别。

译者注上面两种方式创建的对象不能访问 Bar 原型链上的属性,如下所示:

var bar1 = new Bar();
typeof(bar1.method); // "function"
typeof(bar1.foo); // "undefined"

var bar2 = Bar();
typeof(bar2.method); // "function"
typeof(bar2.foo); // "undefined"

通过工厂模式创建新对象

我们常听到的一条忠告是不要使用 new 关键字来调用函数,因为如果忘记使用它就会导致错误。

为了创建新对象,我们可以创建一个工厂方法,并且在方法内构造一个新对象。

function Foo() {
    var obj = {};
    obj.value = 'blub';

    var private = 2;
    obj.someMethod = function(value) {
        this.value = value;
    }

    obj.getPrivate = function() {
        return private;
    }
    return obj;
}

虽然上面的方式比起 new 的调用方式不容易出错,并且可以充分利用私有变量带来的便利,
但是随之而来的是一些不好的地方。

  1. 会占用更多的内存,因为新创建的对象不能共享原型上的方法。
  2. 为了实现继承,工厂方法需要从另外一个对象拷贝所有属性,或者把一个对象作为新创建对象的原型。
  3. 放弃原型链仅仅是因为防止遗漏 new 带来的问题,这似乎和语言本身的思想相违背。

总结

虽然遗漏 new 关键字可能会导致问题,但这并不是放弃使用原型链的借口。
最终使用哪种方式取决于应用程序的需求,选择一种代码书写风格并坚持下去才是最重要的。

分享到:
评论

相关推荐

    Vue组件通信eventbus封装-构造函数方式.zip

    这个压缩包文件"Vue组件通信eventbus封装-构造函数方式.zip"内包含了一个名为`EventBus2.js`的文件,很显然,它是对Vue事件总线的一种实现,使用了构造函数的方式。 首先,我们要理解什么是EventBus。EventBus是一...

    Javascript 设计模式之构造函数模式.zip

    构造函数模式是JavaScript中的一种重要设计模式,用于创建对象。本文将深入探讨构造函数模式及其应用。 构造函数模式的核心在于使用函数来创建具有相似属性和方法的对象。在JavaScript中,函数可以作为构造函数来...

    javascript-数学函数Maths.rar

    javascript-数学函数Maths.rar

    javascript经典特效---函数计算.rar

    在这个"javascript经典特效---函数计算"的资源中,我们可以深入探讨JavaScript函数在实现各种特效时的重要作用。 1. **函数基础**:在JavaScript中,函数是一组相关语句的集合,可以被命名并多次调用。函数定义了可...

    JavaScript应用实例-常用函数-小七.js

    JavaScript应用实例-常用函数-小七.js

    js代码-构造函数模式demo

    在这个"js代码-构造函数模式demo"中,我们将探讨JavaScript中的构造函数模式,这是一种创建对象的常见方式。构造函数模式在面向对象编程中尤为重要,因为它允许我们定义可复用的类模板,进而生成具有相似属性和方法...

    构造函数和实例

    在深入讨论构造函数和实例之前,首先需要了解JavaScript中构造函数的概念。构造函数是一种特殊函数,它主要用于创建和初始化一个新对象。与普通函数不同的是,构造函数通常在使用new操作符时被调用。在JavaScript中...

    JavaScript中的普通函数与构造函数比较

    JavaScript中的普通函数与构造函数是两种不同类型的函数,它们在定义方式、调用方式及作用上都有所区别。普通函数通常是指不依赖于new关键字调用的函数,而构造函数则特指设计用来创建和初始化新对象的函数。接下来...

    JavaScript应用实例-增加函数运行开始和结束的提示.js

    JavaScript应用实例-增加函数运行开始和结束的提示.js

    JavaScript构造函数详解

    在JavaScript中,构造函数是一种特殊类型的函数,用于初始化创建对象。构造函数经常被用于创建具有相似属性和方法的多个对象。JavaScript中构造函数和实例对象之间的关系,以及其背后的原理是JavaScript编程中的一个...

    构造函数以及原型基础

    ### 构造函数以及原型基础 ...通过以上介绍可以看出,理解构造函数和原型的基本概念及其使用方式对于高效地开发JavaScript程序至关重要。这些基础知识不仅帮助我们更好地组织代码,还能有效地管理内存资源。

    JavaScript手册-中文文档

    - 对象创建:通过字面量语法或构造函数创建对象。 - 原型链:理解原型和__proto__,以及如何通过原型实现继承。 - this关键字:在不同上下文中this的指向。 3. **数组与集合**: - 数组方法:如push、pop、...

    第16周-第10章节-Python3.5-JavaScript函数.avi

    第16周-第10章节-Python3.5-JavaScript函数.avi

    js代码-构造函数+原型对象的继承

    在JavaScript中,面向对象编程是基于构造函数和原型对象的继承机制实现的。这是一种非常重要的概念,对于理解和编写复杂的JavaScript程序至关重要。本文将深入探讨构造函数、原型对象以及它们如何协同工作来实现继承...

    第15周-第16章节-Python3.5-javascript函数的定义.avi

    第15周-第16章节-Python3.5-javascript函数的定义.avi

    再践javascript对象、原型、属性、构造函数、扩展、json.docx

    ### JavaScript对象、原型、属性、构造函数、扩展、JSON #### JavaScript对象类型 JavaScript是一种广泛使用的脚本语言,尤其在Web开发中占据了重要的地位。它支持多种对象类型,包括内部对象、基于类的对象以及...

    javascript工厂模式和构造函数模式创建对象方法解析.docx

    ### JavaScript工厂模式与构造函数模式创建对象方法解析 #### 一、工厂模式 在JavaScript中,工厂模式是一种常用的设计模式,用于封装创建对象的过程。它通过一个函数来创建具有相似特性的多个对象实例,这些对象...

    JavaScript教程--从入门到精通

    通过字面量语法或构造函数可以创建对象,原型链则用于实现继承。理解原型和原型链的概念对于深入掌握JavaScript面向对象编程至关重要。 事件和DOM操作是JavaScript与用户交互的基础。事件是用户与网页互动时发生的...

    JavaScript 面向对象与原型

    JavaScript是一种支持两种主要编程范式的语言:函数...总之,JavaScript的面向对象编程依赖于原型机制,通过构造函数和原型链实现了对象的创建、继承和属性/方法的共享。理解这些概念对于深入学习JavaScript至关重要。

    JavaScript进阶基础-3

    - **构造函数创建对象**:使用`new`关键字和`Object`构造函数来创建对象,或者自定义构造函数。 - **工厂模式**:工厂函数是一个返回对象的函数,可以创建具有相同属性和方法的不同对象,体现了面向对象的理念。 - *...

Global site tag (gtag.js) - Google Analytics