我正在测试James Shore的Object Playground,我发现所有方法都继承自Function.prototype,包括全局Object.prototype上的方法。这是如何运作的?那不是圆形吗?我的意思是......没有Function.prototype"本身" Object.prototype固有的?那么Object如何固有来自Function.prototype的东西呢? Isn只是一个函数的子类型吗?不管对象本身是否包含这些行为?为什么需要继承?
答案 0 :(得分:2)
Object.prototype 是原型链中的最后一个,它不会从任何东西继承。 Object 构造函数是继承自 Function.prototype 的构造函数,因为它只是一个函数;它是功能实例。
由于您的问题很普遍,我会尝试描述一些主题,希望您能回答自己的问题。以下是我试图涵盖的主题:
注意:解释JavaScript如何运作可能会很困难,有时会让人感到困惑。我希望你能从中得到一些东西。
"原型"在JavaScript中可能有点混乱。这是因为根据具体情况,至少有两种方法可以使用这个词:
1) "另一个对象的原型对象"
另一个对象的原型对象也被称为"内部原型" ,表示为 [[Prototype]] 或{{ 1}};他们都意味着同样的事情。举个例子,我们来看看这个数组:__proto__
。我们说nums = [9, 8, 7];
是一个数组......但为什么呢?
nums
构造函数的一个实例(构造函数只是函数,除了我们使用 new 关键字< / em>的)。Array
财产。2) &#34;构造函数的原型属性&#34;
继续Array.prototype
数组示例,Array构造函数有一个名为nums
的属性,我们可以像这样访问它:prototype
。这个属性是&#34;内部原型&#34;数组实例,并提供我们用于调用数组的所有方法 - 例如Array.prototype
,forEach
,push
,pop
等。
因此,沿着相同的路线,我的函数join
的内部原型或任何其他函数是foo()
属性中包含的对象;换句话说,Function.prototype
是任何函数&#34;内部原型&#34;宾语。另外,我们可以说 Function 构造函数有一个 prototype 属性,它最终是&#34;内部原型&#34;所有功能。
我所处的地方是我们以两种不同的方式谈论一件事(原型)。在第一种方式中我们说:&#34;原型/内部原型&#34;一个对象,在第二种方式中我们说:&#34;构造函数的原型&#34;属性。
在JavaScript中构造函数与其他编程语言中的类类似。嗯,不太好。实际上,为了类似于类,JavaScript使用构造函数和另一个名为 prototype 的对象的组合。实际上,每个JavaScript函数都会自动获取 prototype 属性,因为函数可以用作构造函数或简单地用作函数。当一个函数不被用作构造函数时,它的 prototype 属性不会被用于任何东西,并且它只是作为一个无用的属性悬挂在那里。
在经典语言中,该类包含实例变量和实例方法,但在JavaScript中,构造函数包含实例变量及其原型对象包含实例方法。
实例变量对于构造函数的特定实例(它们包含特定于实例的数据)是唯一的,并且实例方法由所有实例共享。换句话说,所有实例都可以执行实例方法,但不能访问彼此的变量。
因此,JavaScript中的所有对象都是各自构造函数的实例。例如,Function.prototype
之类的数组是[1,2,3]
构造函数的实例。 function Array() {}
之类的对象是{key: 'value'}
构造函数的实例。 function Object() {}
等JavaScript函数是alert()
构造函数的实例......依此类推。
同样,JavaScript中的所有构造函数都有function Function() {}
属性,此属性包含构造函数实例将继承的方法。
示例:强>
prototype
// Person constructor to create people instances
function Person(name, age) {
// Every instance has its own "instance variables", a.k.a. properties.
this.name = name;
this.age = age;
}
// The "instance methods"
Person.prototype = {
greet: function() {
return 'Hello ' + this.name;
},
//...
};
// Joe is an instance of the `Person` constructor, and Joe's "prototype"
// is the `Person.prototype` object. We call Joe's "prototype" the
// "internal prototype".
var joe = new Person('Joe Doe', 44);
joe.name; //=> Joe Doe
joe.greet(); //=> Hello Joe Doe
构造函数。
Object 构造函数就像上面的 Person 构造函数,除了它创建对象实例而不是人物实例。
Object
构造函数。
功能构造函数就像 Person &amp;上面的 Object 构造函数,除了它创建Function实例,换句话说它创建函数。
Function
,Person
,Object
,Array
,Function
,String
等JavaScript中的所有构造函数都只是功能。由于它们是函数,因此意味着它们是在语言内部使用Boolean
创建的,并且new Function
和call()
等所有函数方法都来自 Function.prototype 。换句话说, Function.prototype 是&#34;原型/内部原型&#34;所有函数的对象,包括构造函数和函数apply()
本身。
<强>结论:强>
不要将构造函数的Function
属性(包括未来实例将使用的方法)与构造函数本身的内部原型混淆。
但是,请记住构造函数的prototype
属性是构造函数实例的内部[[Prototype]]。例如,prototype
是Function.prototype
构造函数的内部[[Prototype]],这是有道理的,因为Object
构造函数只是另一个函数(Object
实例)
对于代码结论,请看一下Object&amp;函数构造函数在JavaScript内部创建:
Function
答案 1 :(得分:1)
JavaScript是一种基于原型的语言。这意味着技术上没有“类”。只有原型,描述对象。每个对象都有一个原型。原型本身实际上是一个对象。 (令人困惑吧?如果你不能把它包裹起来,请不要过于考虑它。它会在某个时候点击。只要知道原型是你可以修改的对象。/ p>
在继续之前,我想指出我的代码示例不符合正确或最佳做法。我编写的代码示例纯粹是为了演示或解释一个概念。
让我们看看一些代码:
Object.toString(); // "[object Object]"
Object.prototype.toString(); // "[object Object]"
Object.hasOwnProperty('toString'); // true
typeof Object; // "function"
typeof Object.prototype // "object"
var obj = new Object();
obj.toString(); // "[object Object]"
obj.hasOwnProperty('toString'); // false
obj.toString = function() {
return 'My Object';
};
obj.toString(); // "My Object"
obj.hasOwnProperty('toString') // true
obj.__proto__.toString(); // "[object Object]"
typeof obj; // "object"
typeof obj.__proto__; // "object"
您可能还注意到typeof Object
返回"function"
。这是因为Object实际上是一个构造函数方法,用于实例化新对象。我的实例对象实际上是typeof obj === "object"
。
正如您在上面的代码中看到的那样,Object
包含一个名为toString
的方法。但Object
的实例却没有。 obj
没有自己的toString
方法。但您仍然可以在toString
上致电obj
。 JavaScript通过遵循原型链来完成继承。
我可以覆盖obj.toString
以使obj
拥有自己的toString
方法,但obj.__proto__
属性仍然拥有其toString
方法prototype
}。
如果有问题的对象不包含自己的属性toString
,那么该属性将查看其原型。如果它自己的原型不包含属性toString
,则查找将继续原型链直到找到属性。如果原型是null
,则表示属性为undefined
。
是的,在最核心,最终在原型链中,每个对象都是一个JavaScript对象。包括Functions
。
var func = function() {};
func.__proto__ //function Empty() {}
func.__proto__.__proto__ // Object {}
func.__proto__.isPrototypeOf(Object) // true
因此函数是JavaScript中的对象。这就是为什么你可以将属性附加到函数。
所有方法都继承自Function.prototype
不,所有方法都不会从Function
继承。方法是 Function
。
那么Object.prototype如何固有来自Function.prototype的东西?
Object不会从Function继承任何内容。对象可以使用功能,例如toString
方法。
Object
有点演示复合设计模式。 (除了可以向引用自身的对象添加属性和/或创建循环引用之外)
来自[http://en.wikipedia.org/wiki/Composite_pattern]
在软件工程中,复合模式是一种分区设计模式。复合模式描述了一组对象的处理方式与对象的单个实例相同。复合的意图是将对象“组合”成树结构以表示部分整体层次结构。
因为Object
包含多个属性,这些属性也都是Object
。
那么它是否循环?不,不是真的。但它肯定是递归的。
您可以在此处详细了解JavaScript原型:http://blog.pluralsight.com/understanding-javascript-prototypes
请注意,ES6在JavaScript中引入了实际的类。这与我上面解释的一切不同。 ES6 class
是我还没有玩过的东西。