Javascript 函数对象的属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15174187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 23:46:07  来源:igfitidea点击:

Properties of Javascript function objects

javascriptoopprototypeprototypal-inheritance

提问by testndtv

I have a JavaScript function object as;

我有一个 JavaScript 函数对象;

var addNum = function(num1, num2) {
        return num1 + num2;
}

Now if I try to access

现在,如果我尝试访问

addNum.divide()

I wanted to understand the prototype chain for the above code. I read that in the above example, addNum would be searched for divide(), followed by Function.prototype and finally Object.prototype.

我想了解上述代码的原型链。我在上面的例子中读到,addNum 将搜索divide(),然后是Function.prototype,最后是Object.prototype。

But my question is in the above example, how can addNum would be searched for divide()

但我的问题是在上面的例子中,如何在 addNum 中搜索divide()

Does it refer to something like ;

它是指类似的东西吗?

var addNum = function(num1, num2) {

this.divide = function(){}

            return num1 + num2;
    }

I could not understand the line where it says addNum would be searched for divide()

我无法理解它说 addNum 将被搜索divide() 的那一行

Please help me understand the same.

请帮助我理解相同。

回答by Keith Morris

I'm not sure this will answer your question but may give you some insight. Consider the following example:

我不确定这会回答你的问题,但可能会给你一些见解。考虑以下示例:

var Person = (function () {
    var Person = function (name) {
        this.name = name;
    }

    Person.greet = function () {
        console.log("Hello!");
    }

    Person.prototype = {
        greet: function () {
            console.log('Hello, my name is ' + this.name);
        }
    };
    return Person;
})();

var bob = new Person("Bob");

Person.greet(); // logs "Hello!"
bob.greet(); // logs "Hello, my name is Bob

The function object "Person" has a direct 'greet' property that is a Function. OOP-wise, you can almost think of that as a static method that can be called directly from the Person Function (Person.greet()). Once you "instantiate" a person object from the Person constructor, that new object "bob" now references it's methods from the Person.prototype object. Now when you call bob.greet(), it uses the greet function in the prototype object.

函数对象“Person”有一个直接的“greet”属性,它是一个函数。在 OOP 方面,您几乎可以将其视为可以直接从 Person 函数 (Person.greet()) 调用的静态方法。一旦你从 Person 构造函数“实例化”了一个 person 对象,这个新对象“bob”现在从 Person.prototype 对象引用它的方法。现在当你调用 bob.greet() 时,它使用原型对象中的 greet 函数。

Hope that helps.

希望有帮助。

回答by Elias Van Ootegem

As you say so yourself: you have a function object. Functions are objects in JS, just like Object literals, arrays, or anything else: a function can be assigned properties and methods at will:

正如您自己所说:您有一个函数object。函数是 JS 中的对象,就像对象字面量、数组或其他任何东西:一个函数可以随意分配属性和方法:

var someAnonFunction = function(foo)
{
    console.log(this);
    console.log(this === someAnonFunction);//will be false most of the time
};
someAnonFunction.x = 123;//assign property
someAnonFunction.y = 312;
someAnonFunction.divide = function()
{
    console.log(this === someAnonFunction);//will be true most of the time
    return this.x/this.y;//divide properties x & y
};
someAnonFunction.divide();

In this case, the function object, referenced by someAnonFunctionhas been assigned a reference to the anonymous function, called divide(well, the reference to an anonymous function was dubbed divide anyway). So there is no prototype involvement at all here. Mind you, as you say so yourself: all objects can be traced back to Object.prototype, just try this:

在这种情况下,被引用的函数对象someAnonFunction被分配了一个对匿名函数的引用,被调用divide(好吧,对匿名函数的引用无论如何都被称为divide)。所以这里根本没有原型参与。请注意,正如您自己所说:所有对象都可以追溯到Object.prototype,试试这个:

console.log(someAnonFunction.toString === Function.prototype.toString);//functions are stringified differently than object literals
console.log(someAnonFunction.hasOwnProperty === Object.prototype.hasOwnProperty);//true

Or, perhaps this is more clear: a simple scheme of how a method/property call is resolved to a value in JS:

或者,也许这更清楚:方法/属性调用如何解析为 JS 中的值的简单方案:

[      F.divide      ]<=========================================================\ \
F[divide] ===> JS checks instance for property divide                           | |
 /\ ||                                                                          | |
 || || --> property found @instance, return value-------------------------------| |
 || ||                                                                          | |
 || ===========> Function.prototype.divide could not be found, check prototype  | |
 ||      ||                                                                     | |
 ||      ||--> property found @Function.prototype, return-----------------------| |
 ||      ||                                                                     | |
 ||      ==========> Object.prototype.divide: not found check prototype?        | |
 ||          ||                                                                 | |
 ||          ||--> property found @Object.prototype, return---------------------|_|
 ||          ||                                                                 |=|
 ||          =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
 ||                                                                             \ /
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined

It therefore follows, that if you want the code above to work using prototypes, you'll have to augment a prototype of sorts (in this case, the Function.prototype). Do know that this isn't to be recommended, in fact changing "native"prototypes is often frowned upon. Still:

因此,如果您希望上面的代码使用原型工作,则必须增加各种原型(在本例中为Function.prototype)。要知道这不是推荐的,实际上改变“原生”原型通常是不受欢迎的。仍然:

Function.prototype.divide = function (a, b)
{
    a = +(a || 0);//coerce to number, use default value
    b = +(b || 1) || 1;//division by zeroe is not allowed, default to 1
    return a/b;
};
function someFunction ()
{
    return 'someString';
};
var another = function(a, b)
{
    return a + b;
};
someFunction.divide(12, 6);//will return 2
another.divide(12, 4);//3

In both cases, the function object, referenced by the name (someFunctionor another) will be scanned for a property called divide, which isn't found. Then however it'll scan the Function.prototype, where such a property is found.
If that weren't the case, JS would also check the Object.prototype, if that failed, it will eventually throw an error.

在这两种情况下,名称 (someFunctionanother) 所引用的函数对象将被扫描以查找名为 的属性divide,但未找到该属性。然后它会扫描Function.prototype,找到这样的属性。
如果不是这样,JS 也会检查Object.prototype,如果失败,它最终会抛出一个错误。

I've posted quite lengthy answers on SO on this subject a while back:

不久前,我在这个主题上发布了很长的答案:

What makes my.class.js so fast?(deals with prototype chains)
Objects and functions in javascript(recap of functions <=> objects <=> constructors)
What are the differences between these three patterns of "class" definitions in JavaScript?(some more info, still)
Javascript - Dynamically change the contents of a function(vaguely touches on the anonymous functions, assigned to variables and properties and changing their context)

是什么让 my.class.js 如此之快?(处理原型链)
javascript 中的对象和函数(函数回顾<=> 对象<=> 构造函数)
JavaScript 中“类”定义的这三种模式有什么区别?(更多信息,仍然)
Javascript - 动态更改函数的内容(模糊地涉及匿名函数,分配给变量和属性并更改它们的上下文)

回答by KooiInc

You can create divideas a [sort of a] staticmethod:

您可以创建divide为 [sort of a]static方法:

var addNum = function(num1, num2) {
  addNum.divide = function(){return num1/num2;};
  return num1 + num2;
}
// now you first have to run addNum
var onethirds = addNum(1,3); //=> 4
addNum.divide(); //=> 0.333333...

But it's not advisable. Better create a constructorfunction:

但这是不可取的。最好创建一个构造函数:

function Pair(n1,n2){
   n1 = n1 || 1;
   n2 = n2 || 1;
   // create instance methods
   this.add      = function(){return n1+n2;};
   this.divide   = function(){return n1/n2;};
   this.multiply = function(){return n1*n2;}
}
var pair1 = new Pair(2,6)
   ,pair2 = new Pair(1,2);
pair1.add();    //=> 8
pair2.divide(); //=> 0.5
//etc.

or a more prototypal approach (methods are added to the constructor prototype, not to every instance):

或者更原型的方法(方法被添加到构造函数原型,而不是每个实例):

function Pair(n1,n2){
   this.n1 = n1 || 1;
   this.n2 = n2 || 1;
   // create prototype methods (once)
   if (!Pair.prototype.add){
    var proto      = Pair.prototype;
    proto.add      = function(){return this.n1+this.n2;};
    proto.divide   = function(){return this.n1/this.n2;};
    proto.multiply = function(){return this.n1*this.n2;}
   }
}

Reading stuff

阅读的东西

回答by Fabian Schmengler

No, your last code only makes sense if you used addNumas a constructor function:

不,您的最后addNum一段代码仅在您用作构造函数时才有意义:

var instance = new addNum();
instance.divide();

However, because functions are objects, the following would be valid:

但是,由于函数是对象,因此以下内容是有效的:

var addNum = function(num1, num2) {
        return num1 + num2;
}
addNum.divide = function() {}

In this case dividewould be a property of addNumitself, not of one of its prototypes.

在这种情况下divideaddNum它是它自身的一个属性,而不是它的一个原型的属性。

回答by gmaliar

To understand prototypal inheritance is somewhat obscure at first, but think of it as the name suggests, there are a few prototypes in JavaScript and Function is one of them.

对原型继承的理解起初有些晦涩,但顾名思义,JavaScript 中有一些原型,Function 就是其中之一。

Whenever you create a new function you can check its type with the typeofcommand. In your case:

每当您创建一个新函数时,您都可以使用该typeof命令检查其类型。在你的情况下:

var a = function(a,b) { return a + b; }

It will return "function"so there are two ways to add to your avariable more methods. One would be, as @Keith Morris suggested, to create a new constructor and have its methods inside and return it. That is also the preferred way because then, you don't pollute the basic objects with prototypal methods which are extended to each and every object that is represented by them.

它将返回,"function"因此有两种方法可以将a更多方法添加到您的变量中。正如@Keith Morris 所建议的那样,一种方法是创建一个新的构造函数并在其中包含其方法并返回它。这也是首选方式,因为这样,您就不会使用扩展到它们所表示的每个对象的原型方法来污染基本对象。

Meaning, if I instead do this:

意思是,如果我改为这样做:

Function.prototype.divide = function(a, b) { return a / b; }

I can now do a.divide(2, 1);and it would return 2. But for example if I use jQueryand do jQuery.divide(2,1)I will also get 2because it tries to find it in the immediate scope of the function. If not, it will go to the prototype of it.

我现在可以做a.divide(2, 1);,它会返回2。但是例如,如果我使用jQuery和执行jQuery.divide(2,1)我也会得到,2因为它试图在函数的直接范围内找到它。如果没有,它将转到它的原型。

Hope this explains it to you a bit better.

希望这能更好地向你解释它。