Javascript函数对象的属性

Javascript函数对象的属性,javascript,oop,prototype,prototypal-inheritance,Javascript,Oop,Prototype,Prototypal Inheritance,我有一个JavaScript函数对象作为 var addNum = function(num1, num2) { return num1 + num2; } 现在如果我尝试访问 addNum.divide() 我想了解上面代码的原型链。我在上面的例子中读到,addNum将被搜索divide(),然后是Function.prototype,最后是Object.prototype 但我的问题是在上面的示例中,如何搜索addNum以查找divide() 它指的是什么 var add

我有一个JavaScript函数对象作为

var addNum = function(num1, num2) {
        return num1 + num2;
}
现在如果我尝试访问

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

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

它指的是什么

var addNum = function(num1, num2) {

this.divide = function(){}

            return num1 + num2;
    }
我不明白它说addNum将被搜索divide()的那一行


请帮助我理解同样的问题。

我不确定这是否能回答您的问题,但可能会给您一些启示。考虑下面的例子:

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
函数对象“Person”有一个直接的“greet”属性,它是一个函数。面向对象,您几乎可以将其视为一个静态方法,可以直接从Person函数(Person.greet())调用。从person构造函数“实例化”person对象后,新对象“bob”现在引用person.prototype对象中的方法。现在,当调用bob.greet()时,它在原型对象中使用greet函数


希望能有所帮助。

不,只有将
addNum
用作构造函数时,您的上一个代码才有意义:

var instance = new addNum();
instance.divide();
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.
但是,由于函数是对象,因此以下内容是有效的:

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

在这种情况下,
divide
将是
addNum
本身的一个属性,而不是它的一个原型的属性。

要理解原型继承,一开始有些模糊,但正如名称所示,JavaScript中有一些原型,函数就是其中之一

无论何时创建新函数,都可以使用
typeof
命令检查其类型。就你而言:

var a = function(a,b) { return a + b; }
它将返回
“function”
,因此有两种方法可以向
变量添加更多方法。正如@Keith Morris所建议的,一种方法是创建一个新的构造函数,并将其方法放入其中并返回。这也是首选的方法,因为这样,您就不会用原型方法污染基本对象,原型方法扩展到它们所表示的每个对象

也就是说,如果我这样做:

Function.prototype.divide = function(a, b) { return a / b; }
我现在可以做
a.divide(2,1)
并返回
2
。但例如,如果我使用
jQuery
并执行
jQuery.divide(2,1)
操作,我也会得到
2
,因为它试图在函数的直接作用域中找到它。如果没有,它将进入它的原型

希望这能更好地向您解释。

正如您自己所说:您有一个函数对象。函数是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();
在这种情况下,
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
或者,这可能更清楚:一个简单的方案,说明如何将方法/属性调用解析为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
在这两种情况下,将扫描名称(
someFunction
other
)引用的函数对象,以查找名为
divide
的属性,但未找到该属性。然而,它将扫描
函数.prototype
,在那里可以找到这样的属性。
如果不是这样,JS还会检查
对象.prototype
,如果失败,它最终会抛出一个错误

不久前,我就这一主题发布了相当长的答案:

(处理原型链)
(函数对象构造函数概述)
(还有更多信息)

(模糊地涉及到分配给变量和属性并更改其上下文的匿名函数)

您可以创建
divide
作为一种[排序]静态
方法:

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...
但这是不可取的。更好地创建一个函数:

var instance = new addNum();
instance.divide();
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.
或者更原型的方法(方法添加到构造函数原型,而不是每个实例):


我在Chrome中运行了你的代码,它说:uncaughttypeerror:Object function(num1,num2){return num1+num2;}没有方法“divide”,你确定这不是架构问题吗?实际上,divide不是addNum的子函数。相反,他们会有一个父类/对象,他们可以共享变量和属性,并对它们进行数学计算?我读了这一行,所以,你的建议正确吗
var addNum=function(num1,num2){this.divide=function(){}返回num1+num2;}
我相信是的?我喜欢这个例子,它很好地解释了原型继承的可能性,如果您添加了另一位代码,那么您现在也可以扩展
函数
构造函数,以进一步展示Javascript的可能性以及原型继承背后的思想。谢谢您的示例。但为什么Person.prototype.constructor会得到问候,而Person不会,拜托?如果你把它们输入你的眼睛,那就对了。我更新了最后一句话,使之更清楚了一点。我重新做了一遍。