简体   繁体   English

JavaScript函数调用或不调用

[英]JavaScript function call or not call

I have two codes of JavaScript,they are the same result of executing,so i am confused and wonder why we use call function. 我有两个JavaScript代码,它们的执行结果相同,所以我很困惑,想知道为什么要使用调用函数。

Not use function call: 不使用函数调用:

<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();     

use function call: 使用函数调用:

<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();     

In this instance, the outcome is the same, but these two code snippets are very different. 在这种情况下,结果是相同的,但是这两个代码段非常不同。 In the first, ClassA is not following the pattern of an object constructor. 首先, ClassA不遵循对象构造函数的模式。 Instead, it takes as its argument an object, and it modifies that object (by adding a property and method to it). 取而代之的是,它将一个对象作为其参数,并修改该对象(通过向其添加属性和方法)。 While the syntax is valid, I would argue that this is poor practice, because naming a function that starts with an uppercase letter usually indicates it is an object constructor, and therefore it should use this , not modify one of its arguments. 虽然语法是有效的,但我认为这是一种不好的做法,因为命名以大写字母开头的函数通常表示它是对象构造函数,因此应使用this而不是修改其参数之一。 It also exhibits inconsistent behavior: 它还表现出不一致的行为:

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

The second example is a more standard example of object construction in JavaScript. 第二个示例是JavaScript中对象构建的更标准示例。 You can create an instance of ClassA by saying new ClassA and you can create an instance of ClassB by calling new ClassB . 您可以创建一个实例ClassAnew ClassA ,你可以创建一个实例ClassB通过调用new ClassB Nice and consistent. 尼斯和一致。

I would go with the second example. 我将举第二个例子。 I would also read up on object models in JavaScript to get a better understanding of what's going on here. 我还将阅读JavaScript中的对象模型,以更好地了解这里发生的事情。 A good place to start is Douglas Crockford's essay on object-oriented programming in JavaScript . 一个很好的起点是Douglas Crockford的关于JavaScript的面向对象编程的文章

I totally agree with what @EthanBrown has said. 我完全同意@EthanBrown所说的。 If you have a function which its responsibility is to modify an object, don't start your function's name with an uppercase letter. 如果您有一个负责修改对象的函数,请不要以大写字母开头该函数的名称。

Other than this, the whole idea behind your code is to add the color and sayColor to the ClassB, which is kind of inheriting. 除此之外,代码背后的整个想法是将colorsayColor添加到ClassB中,这是一种继承。

The point here is, the second snippet is the way we usually implement inheritance in JavaScript. 这里的重点是,第二个片段是我们通常在JavaScript中实现inheritance的方式。 it doesn't mean that your code has completely implemented inheritance , but the idea of using call in a constructor to invoke another constructor is mostly used in inheritance. 这并不意味着您的代码已完全实现inheritance ,但是在constructor函数中大多使用在构造函数中使用call来调用另一个构造函数的想法。 if you want to completely inherit the ClassB from ClassA , the only missing parts is to copy the prototypes, and set the constructor, like this: 如果要从ClassA完全继承ClassB ,则唯一缺少的部分是复制原型并设置构造函数,如下所示:

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

the only drawback in your second snippet is not using prototype , you better use it to create the sayColor and sayName function, and if you completely implement the inheritance in your code, using the 2 lines above, then you can easily do this: 第二个片段的唯一缺点是不使用prototype ,最好使用它来创建sayColorsayName函数,如果使用上述两行代码在代码中完全实现了继承,那么您可以轻松地做到这一点:

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

then you can create you ClassB instance: 然后可以创建您的ClassB实例:

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

and the most important point here is: 最重要的一点是:

objB instanceof ClassA;
objB instanceof ClassB;

both are true. 两者都是对的。


you can create a simple inherit method like: 您可以创建一个简单的继承方法,例如:

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

then use it like: 然后像这样使用它:

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 is used when you want to control the scope that will be used in the function called(we inject the scope inside the function). 当您要控制将在调用的函数中使用的范围时,将使用call (我们将范围注入到函数内部)。 You might want the this keyword to be something else than the scope you assigned the function to, in those cases you need to use call or apply to bring the right scope into the function. 您可能希望this关键字是您为其分配功能的范围之外的其他东西,在这种情况下,您需要使用call或应用将正确的范围带入功能。

Some example: 一些例子:

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

After calling ClassA function we extend WINDOW object, and now you call window.sayColor method. 调用ClassA函数后,我们扩展了WINDOW对象,现在您调用window.sayColor方法。

So we use call method in your example to extend ClassB object 所以我们在您的示例中使用call方法扩展ClassB对象

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

Now when you write next code: 现在,当您编写下一个代码时:

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

the non-call way is just like this, in the constructor of ClassB, the function ClassA is called to add a property and method to current ClassB instance. 非调用方式就是这样,在ClassB的构造函数中,调用ClassA函数为当前ClassB实例添加属性和方法。 in this case, obj in ClassA points to current ClassB's object. 在这种情况下,ClassA中的obj指向当前ClassB的对象。

in the call way, in the constructor of ClassB, call function ClassA but change its execution context to current ClassB object. 以调用方式,在ClassB的构造函数中,调用函数ClassA,但将其执行上下文更改为当前的ClassB对象。 in this case, the 'this' points to ClassB's object. 在这种情况下,“ this”指向ClassB的对象。

so in the above two cases, obj and this in ClassA both point to ClassB objects. 因此在以上两种情况下,ClassA中的obj和this都指向ClassB对象。

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

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