我有一个JavaScript函数对象;
var addNum = function(num1, num2) {
return num1 + num2;
}
现在,如果我尝试访问
addNum.divide()
我想了解上面的代码原型链。 我读的是,在上述例子中,将addNum被搜索除(),随后Function.prototype的最后的Object.prototype。
但我的问题是,在上面的例子中,如何addNum会被搜索鸿沟()
它指的是这样;
var addNum = function(num1, num2) {
this.divide = function(){}
return num1 + num2;
}
它说:addNum将搜索鸿沟我也不懂行的()
请帮助我了解的一样。
我不知道这会回答你的问题,但可以给你一些启示。 请看下面的例子:
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
该函数对象“人”有着直接的“打招呼”属性,它是一个功能。 OOP的角度来看,你几乎可以想到的,作为一个静态方法,可以直接从人函数被调用(Person.greet())。 一旦你“实例”,从人构造一个Person对象,即新对象“鲍勃”现在的方法引用从Person.prototype的对象。 现在,当你调用bob.greet(),它使用的原型对象的greet函数。
希望帮助。
正如你这么说自己: 你有一个函数对象 。 函数是在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
(以及,提及一个匿名函数被冠以除法反正)。 所以,在这里都没有原型的参与。 你要知道,你这样自己说:所有的对象都可以追溯到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
由此得出,如果你想上面的代码中使用原型的工作,你必须增加一个原型各种各样的(在这种情况下, 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
在这两种情况下,所述功能对象,由名称(引用someFunction
或another
)将被扫描的一个名为属性divide
,这是没有找到。 然而然后它会扫描Function.prototype
,在这样的属性没有被找到。
如果不是这样的话,JS也将检查Object.prototype
,如果失败了,它最终将抛出一个错误。
我已经张贴在SO相当长的回答上这个问题而回:
是什么让my.class.js这么快? (与原型链交易)
在javascript对象和函数 (的<=>对象功能概括<=>构造函数)
什么是JavaScript中的“类”的定义这三种模式之间的差异? (一些更多的信息,仍然)
使用Javascript -动态改变函数的内容 (隐约倒是匿名函数,赋值给变量和属性,并改变它们的上下文)
您可以创建divide
为[不大不小的的] 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...
但它是不可取的。 更好地创造一个构造函数:
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.
或者更原型方法(方法添加到构造函数的原型,而不是每个实例):
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;}
}
}
阅读的东西
不,你的最后一个代码才有意义,如果你使用addNum
作为一个构造函数:
var instance = new addNum();
instance.divide();
然而,因为函数是对象,下面是有效的:
var addNum = function(num1, num2) {
return num1 + num2;
}
addNum.divide = function() {}
在这种情况下divide
将是一个财产addNum
本身,而不是它的原型之一。
要理解原型继承起初有点模糊,但认为它顾名思义,也有JavaScript的一些原型,功能就是其中之一。
当你创建一个新的功能,你可以检查它与类型typeof
命令。 你的情况:
var a = function(a,b) { return a + b; }
它会返回"function"
所以有两种方式添加到您的a
变量的详细方法。 其中之一是,作为@Keith莫里斯建议,创建一个新的构造,并有其方法内返回。 这也是首选方法,因为这样,你不污染与扩展到每一个对象是他们所代表原型方法的基本对象。
也就是说,如果我不是这样做:
Function.prototype.divide = function(a, b) { return a / b; }
我现在可以做a.divide(2, 1);
并且它会返回2
。 但是,例如,如果我使用jQuery
,做jQuery.divide(2,1)
我也将获得2
,因为它试图找到它在功能上的直接范围。 如果不是,它会去到它的原型。
希望这是向你解释好一点。