JavaScript has no classes class-based object model. It uses the mightier prototypical inheritance, which can mimic classes, but is not suited well for it. Everything is an object, and objects [can] inherit from other objects.
构造函数只是一个为新创建的对象分配属性的函数。该对象(通过调用创建new keyword https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/new)可以通过this keyword https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this(这是函数的局部)。
方法也只是一个被调用的函数on一个物体 - 再次与this
指向该物体。至少当该函数作为对象的属性调用时,使用会员经营者 https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Member_Operators(点、括号)。这会给新手带来很多困惑,因为如果您传递该函数(例如传递给事件侦听器),它就会与访问它的对象“分离”。
现在遗产在哪里? “类”的实例继承自同一原型对象。方法被定义为该对象上的函数属性(而不是每个实例一个函数),您调用它们的实例仅继承该属性。
Example:
function Foo() {
this.bar = "foo"; // creating a property on the instance
}
Foo.prototype.foo = 0; // of course you also can define other values to inherit
Foo.prototype.getBar = function() {
// quite useless
return this.bar;
}
var foo = new Foo; // creates an object which inherits from Foo.prototype,
// applies the Foo constructor on it and assigns it to the var
foo.getBar(); // "foo" - the inherited function is applied on the object and
// returns its "bar" property
foo.bar; // "foo" - we could have done this easier.
foo[foo.bar]; // 0 - access the "foo" property, which is inherited
foo.foo = 1; // and now overwrite it by creating an own property of foo
foo[foo.getBar()]; // 1 - gets the overwritten property value. Notice that
(new Foo).foo; // is still 0
因此,我们只使用了该对象的属性并且对此感到满意。但它们都是“公开的”,并且可以被覆盖/更改/删除!如果这对你来说并不重要,那么你很幸运。您可以通过在属性名称前添加下划线来指示属性的“私有性”,但这只是对其他开发人员的提示,可能不会被遵守(尤其是在错误时)。
因此,聪明的人找到了一种解决方案,使用构造函数作为闭包,允许创建私有“属性”。 javascript 函数的每次执行都会为局部变量创建一个新的变量环境,一旦执行完成,这些变量可能会被垃圾回收。在该作用域内声明的每个函数也可以访问这些变量,并且只要可以调用这些函数(例如通过事件侦听器),环境就必须持续存在。所以,通过导出本地定义的函数从构造函数中,您可以使用只能由这些函数访问的局部变量来保留该变量环境。
让我们看看它的实际效果:
function Foo() {
var bar = "foo"; // a local variable
this.getBar = function getter() {
return bar; // accesses the local variable
}; // the assignment to a property makes it available to outside
}
var foo = new Foo; // an object with one method, inheriting from a [currently] empty prototype
foo.getBar(); // "foo" - receives us the value of the "bar" variable in the constructor
这个在构造函数内部定义的 getter 函数现在称为“特权方法”,因为它可以访问“私有”(本地)“属性”(变量)。bar
永远不会改变。当然,您还可以为其声明一个 setter 函数,并且您可以添加一些验证等。
请注意,原型对象上的方法无权访问构造函数的局部变量,但它们可能使用特权方法。让我们添加一个:
Foo.prototype.getFooBar = function() {
return this.getBar() + "bar"; // access the "getBar" function on "this" instance
}
// the inheritance is dynamic, so we can use it on our existing foo object
foo.getFooBar(); // "foobar" - concatenated the "bar" value with a custom suffix
因此,您可以结合使用这两种方法。请注意,特权方法需要更多内存,因为您创建具有不同作用域链(但代码相同)的不同函数对象。如果您要创建数量惊人的实例,则应该仅在原型上定义方法。
当您设置从一个“类”到另一个“类”的继承时,它会变得更加复杂 - 基本上,您必须使子原型对象从父类继承,并将父构造函数应用于子实例以创建“私有属性” ”。看一下正确的 javascript 继承 https://stackoverflow.com/q/10898786/1048572, 继承原型中的私有变量 https://stackoverflow.com/q/3617139/1048572, 在 JAVASCRIPT 模块模式中定义私有字段成员和继承 https://stackoverflow.com/q/12463040/1048572 and JS Revealing原型模式如何实现继承? https://stackoverflow.com/q/9248655/1048572