繁体   English   中英

JavaScript函数调用或不调用

[英]JavaScript function call or not call

我有两个JavaScript代码,它们的执行结果相同,所以我很困惑,想知道为什么要使用调用函数。

不使用函数调用:

<script language="javascript">
function ClassA(obj, sColor) {
    obj.color = sColor;
    obj.sayColor = function() {
        alert(obj.color);
    };
}
function ClassB(sColor, sName) {
    ClassA(this, sColor);
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();     

使用函数调用:

<script language="javascript">
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function() {
        alert(this.color);
    };
}

function ClassB(sColor, sName) {
    ClassA.call(this,sColor);
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();     

在这种情况下,结果是相同的,但是这两个代码段非常不同。 首先, ClassA不遵循对象构造函数的模式。 取而代之的是,它将一个对象作为其参数,并修改该对象(通过向其添加属性和方法)。 虽然语法是有效的,但我认为这是一种不好的做法,因为命名以大写字母开头的函数通常表示它是对象构造函数,因此应使用this而不是修改其参数之一。 它还表现出不一致的行为:

var objA = new ClassA();   // will throw error
var objB = new ClassB();   // valid object constructor

第二个示例是JavaScript中对象构建的更标准示例。 您可以创建一个实例ClassAnew ClassA ,你可以创建一个实例ClassB通过调用new ClassB 尼斯和一致。

我将举第二个例子。 我还将阅读JavaScript中的对象模型,以更好地了解这里发生的事情。 一个很好的起点是Douglas Crockford的关于JavaScript的面向对象编程的文章

我完全同意@EthanBrown所说的。 如果您有一个负责修改对象的函数,请不要以大写字母开头该函数的名称。

除此之外,代码背后的整个想法是将colorsayColor添加到ClassB中,这是一种继承。

这里的重点是,第二个片段是我们通常在JavaScript中实现inheritance的方式。 这并不意味着您的代码已完全实现inheritance ,但是在constructor函数中大多使用在构造函数中使用call来调用另一个构造函数的想法。 如果要从ClassA完全继承ClassB ,则唯一缺少的部分是复制原型并设置构造函数,如下所示:

ClassB.prototype = Object.create(ClassA.prototype);
ClassB.constructor = ClassA;

第二个片段的唯一缺点是不使用prototype ,最好使用它来创建sayColorsayName函数,如果使用上述两行代码在代码中完全实现了继承,那么您可以轻松地做到这一点:

ClassA.prototype.sayColor = function() {
    alert(this.color);
};
ClassB.prototype.sayName = function() {
    alert(this.color);
};

然后可以创建您的ClassB实例:

var objB = new ClassB("red", "Luke");
objB.sayColor();
objB.sayName();

最重要的一点是:

objB instanceof ClassA;
objB instanceof ClassB;

两者都是对的。


您可以创建一个简单的继承方法,例如:

function inherit(class, baseClass){
    class.prototype = Object.create(baseClass.prototype);
    class.constructor = baseClass;
}

然后像这样使用它:

function ClassA(sColor) {
    this.color = sColor;
}
ClassA.prototype.sayColor = function() {
    alert(this.color);
};
function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}
ClassB.prototype.sayName = function() {
    alert(this.color);
};
inherit(ClassB, ClassA);

当您要控制将在调用的函数中使用的范围时,将使用call (我们将范围注入到函数内部)。 您可能希望this关键字是您为其分配功能的范围之外的其他东西,在这种情况下,您需要使用call或应用将正确的范围带入功能。

一些例子:

function ClassA(sColor) {
    // if we say ClassA.call(window), **this** will be window (inject)
    this.color = sColor;
    this.sayColor = function() {
        alert(this.color);
    };
} 

// use call method
ClassA.call(window, "red");
ClassA.call(document, "blue"); // after this document will have sayColor method

调用ClassA函数后,我们扩展了WINDOW对象,现在您调用window.sayColor方法。

所以我们在您的示例中使用call方法扩展ClassB对象

function ClassB(sColor, sName) {
    ClassA.call(this,sColor);
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

现在,当您编写下一个代码时:

var b = new ClassB("Color", "Name");
// b will have sayName method, sayColor method

非调用方式就是这样,在ClassB的构造函数中,调用ClassA函数为当前ClassB实例添加属性和方法。 在这种情况下,ClassA中的obj指向当前ClassB的对象。

以调用方式,在ClassB的构造函数中,调用函数ClassA,但将其执行上下文更改为当前的ClassB对象。 在这种情况下,“ this”指向ClassB的对象。

因此在以上两种情况下,ClassA中的obj和this都指向ClassB对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM