Javascript私有/公共继承语法
Javascript Private/Public Inheritence Syntax
我在Javascript中将私有/公共方法与继承结合起来时遇到了问题。我认为这只是我的一个误解,希望能很容易地解决。
这是我所拥有的:
RB = {};
RB.Fruit = function() {
// Public
this.getType = function() {
return "FRUIT";
}
}
RB.Orange = function() {
// Private
function makeOrangeJuice() {
console.log("Orange has been squeezed.");
}
// Public
return {
getName : function() {
return "Orange";
}
}
}
RB.Orange.prototype = new RB.Fruit();
var o = new RB.Orange();
console.log(o.getType());
当我运行此代码时,我收到错误"UnaughtTypeError:Object#没有方法'getType'"。我知道这与在类函数中使用"return"有关(因为将getName方法从"return"块中移出可以使其工作),但我希望继续能够在类中声明私有/公共方法。
我该如何修改它以允许RB.Orange访问RB.Fruit.getType函数?
谢谢!
在JavaScript中,构造函数调用隐式返回新构建的实例,但构造函数可以通过显式返回不同的对象来覆盖默认行为。例如,如果您定义一个"构造函数"Foo
,如下所示:
function Foo() {
return new Date();
}
则语句foo = new Foo()
将foo
设置为新的Date
、而不是设置为新Foo
。
如果我正确理解你想要什么,你只需要改变这个:
return {
getName : function() {
return "Orange";
}
}
(由此,您的"构造函数"返回一个全新的对象,只有一个getName
方法,与正在构建的对象没有关系):
this.getName = function() {
return "Orange";
};
(从而将getName
方法添加到正在构建的对象中,并且仍然允许返回该对象)。
主要问题
当您从构造函数返回非基元值时,将返回该无基元,而不是使用new
关键字调用它时所期望的默认返回实例。
例如
function A() { return {}; }
new A() instanceof A; //false
因此,您可以简单地将代码更改为以下内容:
RB.Orange = function() {
// Private
function makeOrangeJuice() {
console.log("Orange has been squeezed.");
}
this.getName = function () {
return 'Orange';
};
//priviledged function which uses a private member
this.someOtherFunction = function () {
makeOrangeJuice();
};
};
代码中的一些低效率
为什么不使用prototype
不应在构造函数函数中声明不是特权的函数。换句话说,不访问私有变量的函数不应该在构造函数中创建,因为它们不必创建,而且这样做效率极低。为什么?因为每次调用构造函数时都会创建一个新函数。
相反,您应该使用Constructor.prototype
在所有实例之间共享您的公共函数。
例如
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log('My name is ' + this.name);
};
new Person('Foo Bar').sayName();
尽可能使用Object.create
而不是new
进行继承
大多数使用new
关键字的继承模式都是这样做的,因为该语言缺乏另一种设置对象原型链的方法,但现在我们有了Object.create
,您应该使用它。以这种方式使用new
关键字进行继承会产生一些不希望有的副作用,比如运行构造函数。有一些方法可以通过使用中间空函数来避免这些副作用,但为什么不简单地使用Object.create
呢?
例如(基于上述示例)
function BadPerson(name) {
//call parent constructor
Person.call(this, name + ' the bad');
}
BadPerson.prototype = Object.create(Person.prototype);
BadPerson.prototype.constructor = BadPerson; //fix constructor
私人功能也可以共享
请注意,不访问私有变量的私有函数也可以共享。您可以使用模块模式为它们创建一个范围。
例如
var Person = (function () {
//private function used in a functionnal style
function _validateName(name) {
console.log('Validating the name in functionnal style');
}
//private function used in an OO style
function _validateNameOO() {
console.log('Validating the name in a OO style');
}
function Person(name) {
this.name = name;
}
Person.prototype.validateNameBothWays = function () {
_validateName(this.name);
_validateNameOO.call(this);
};
return Person;
})();
new Person().validateNameBothWays();
下面展示了如何实现共享私有成员,以及将具有特权的方法(可以访问共享私有的方法)放在哪里;
我从来没有发现这种模式有多大用处,通常用_aPrivate这个名字来表示private,正如菲利普在回答中所解释的那样。
有关构造函数、原型、继承和this
值的介绍,请单击此处。
RB = {};
RB.Fruit = function() {
}
// Public
RB.Fruit.prototype.getType = function() {
return "FRUIT";
};
RB.Orange = function() {
//inherit instance specific values of Fruit (there are none but there might be)
RB.Fruit.apply(this,arguments);
};
//inherit shared members from the prototype of Fruit
RB.Orange.prototype = Object.create(RB.Fruit.prototype);
//repair constructor to be Orange instead of Fruit
RB.Orange.prototype.constructor = RB.Orange;
//shared privates and privileged methods (methods that can access the privates)
// go in the following IIFE function body.
(function(){
//private version of makeOrangeJuice
var makeOrangeJuice = function () {
//the value of 'this' here isn't the Orange instance
//if you need it then pass it with the public version of
//makeOrangeJuice or use makeOrangeJuice.call(this) in the
//public version
console.log("Orange has been squeezed.");
};
//public version of makeOrangeJuice
RB.Orange.prototype.makeOrangeJuice=function(){
//call private makeOrangeJuice function
makeOrangeJuice();
}
}());
//non privileged member, in getName the private version of makeOrangeJuice
//doesn't exist you can call the public version with this.makeOrangeJuice
RB.Orange.prototype.getName = function() {
return "Orange";
};
var o = new RB.Orange();
console.log(o.getType());
o.makeOrangeJuice();
如果希望继承这些函数,则需要将它们分配给对象的原型。
RB = {};
RB.Fruit = function() {};
RB.Fruit.prototype.getType = function() {
return 'Fruit';
};
RB.Orange = function() {};
RB.Orange.prototype = new RB.Fruit();
RB.Orange.prototype.getName = function() {
return 'Orange';
};
如果您真的需要使用private,并且不能使用诸如_name之类的约定将事物标记为private,那么您需要将使用private的函数移动到具有private成员的构造函数中。
如果它们不是特定于实例的,那么您可以(也应该)用一个立即函数来包装整个过程。
(function() {
// All previous code here
window.RB = RB;
}());
这里有一种方法:
var RB = {};
RB.Fruit = function() {
// Public
this.getType = function() {
return "FRUIT";
}
}
RB.Orange = function() {
// Private variable
var fruit = new RB.Fruit();
// Private function
function makeOrangeJuice() {
console.log("Orange has been squeezed.");
}
// Public object with accessor
return {
getName : function() {
return "Orange";
},
getType: fruit.getType
}
}
var o = new RB.Orange();
console.log(o.getType());
试试这个代码。
RB = {};
RB.Fruit = function() {
// Public
this.getType = function() {
return "FRUIT";
}
}
RB.Fruit.prototype.getType = function() {
return "FRUIT";
};
RB.Orange = function() {
RB.Fruit.call(this);
// Private
function makeOrangeJuice() {
console.log("Orange has been squeezed.");
}
this.getName = function() {
return "Orange";
};
this.getJuice = function(){
makeOrangeJuice();
};
};
var o = new RB.Orange();
//calling the super-call's function
console.log(o.getType());
//public function
o.getJuice();
//trying to access private function
o.makeOrangeJuice();
有关面向ojbect的javscript plz代码的更多详细信息,请查看下面的链接http://mckoss.com/jscript/object.htm
- 铬:“;未捕获的语法错误:意外的标记:"
- jQuery语法添加了var
- Javascript未捕获语法错误意外的标识符错误
- 为什么忽略了eval()代码中的语法错误
- 难以访问的JS环境中的语法错误
- 如何告诉MathJax对下标使用替代语法
- Javascript语法向设置发出sessionStorage值
- 从控制器继承了隔离的作用域以生成可重用的指令
- 未捕获的语法错误:意外的标记{
- 使用$scope方法时的ControllerAs语法
- "未捕获的语法错误:意外的标记}"
- javascript自执行函数-不同的语法
- 函数的Javascript语法
- WinJS内联绑定语法
- 当使用控制器作为语法时,如何从父指令继承属性
- Dojo AMD 1.7使用declare的正确继承语法
- 具有简洁原型赋值语法的Javascript继承
- Javascript私有/公共继承语法
- 如何使用“继承”从基本控制器继承;控制器为“;语法
- javascript中正确的继承语法