Javascript私有/公共继承语法

Javascript Private/Public Inheritence Syntax

本文关键字:继承 语法 私有 Javascript      更新时间:2023-09-26

我在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