JavaScript:继承和常量声明

发布于 2024-07-16 20:08:07 字数 188 浏览 6 评论 0原文

帮助, 我有这个类,

var jMath = {

    pi2: Math.PI,

    foo: function() {
        return this.pi2;
    }
}

我想让 pi2 常量,并且我希望 jMath 从 Math 对象继承。 我怎么做?

Help,
I have this class

var jMath = {

    pi2: Math.PI,

    foo: function() {
        return this.pi2;
    }
}

I want to make the pi2 constant and i want jMath to inherit from Math object. How do I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陪你到最终 2024-07-23 20:08:07

哦,有趣的是,从头开始,这是正确的版本:(

function JMath() {
   this.foo = function() {
        return this.PI;
    }
}

JMath.prototype = Math;

var jMath = new JMath();
alert(jMath.foo());

与此处的其他答案相匹配)

(我最初尝试使用“JMath.prototype = new Math()”设置原型,这就是我所看到的其他地方,但上面的作品)

编辑

这是作为单例执行此操作的一种方法

//  Execute an inline anon function to keep
//  symbols out of global scope
var jMath = (function()
{
    //  Define the JMath "class"
    function JMath() {
        this.foo = function() {
            return this.PI;
        }
    }

    JMath.prototype = Math;

    // return singleton
    return new JMath();
})();

//  test it
alert( jMath.PI );

//  prove that JMath no longer exists
alert( JMath );

Oh amusing, scratch all that, this is the correct version:

function JMath() {
   this.foo = function() {
        return this.PI;
    }
}

JMath.prototype = Math;

var jMath = new JMath();
alert(jMath.foo());

(which matches what the other answer is here)

(I originally tried to set the prototype using "JMath.prototype = new Math()" which is how I've seen it other places, but the above works)

Edit

Here's one way to do it as a singleton

//  Execute an inline anon function to keep
//  symbols out of global scope
var jMath = (function()
{
    //  Define the JMath "class"
    function JMath() {
        this.foo = function() {
            return this.PI;
        }
    }

    JMath.prototype = Math;

    // return singleton
    return new JMath();
})();

//  test it
alert( jMath.PI );

//  prove that JMath no longer exists
alert( JMath );
西瑶 2024-07-23 20:08:07

考虑使用原型:

function JMath() {};
JMath.prototype = {
    pi2: Math.PI,

    foo: function() {
        return this.pi2;
    }
}

var j = new JMath(); 
j.pi2=44; j.foo(); // returns 44
delete j.pi2; j.foo(); // now returns Math.PI

这和@altCognito的答案之间的区别在于,这里对象的字段是共享的,并且都指向相同的东西。 如果不使用原型,则可以在构造函数中创建新的未链接的实例。 您可以在每个实例的基础上覆盖原型的值,如果您覆盖它然后决定不喜欢覆盖值并想要恢复原始值,请使用 delete 删除覆盖只是“掩盖”了原型的价值。

编辑:如果您想继承Math对象本身的所有方法和字段,但在不影响Math对象的情况下覆盖某些内容,请执行以下操作(根据您的喜好更改名称“Constructor1”):

function Constructor1() {};
Constructor1.prototype = Math;
function JMath() {};
JMath.prototype = new Constructor1();
JMath.prototype.pi2 = JMath.prototype.PI;
JMath.prototype.foo = function() { return this.pi2; }

var j = new JMath();
j.cos(j.foo()); // returns -1

编辑3:解释Constructor1 函数:这将创建以下原型链:

j -> JMath.prototype -> Math

j 是 JMath 的实例。 JMath 的原型是Constructor1 的一个实例。 Constructor1 的原型是 Math。 JMath.prototype 是被覆盖的东西“生存”的地方。 如果您只实现 JMath 的几个实例,则可以将覆盖的内容作为构造函数 JMath 设置的实例变量,并直接指向 Math,就像 @altCognito 的答案所做的那样。 (j 是 JMath 的实例,JMath 的原型是 Math)

在构造函数中增强对象有 2 个缺点。 (实际上不一定有缺点)一是在构造函数中声明实例字段/方法为每个实例创建单独的值。 如果创建大量 JMath 实例,每个实例的 JMath.foo 函数将是一个单独的对象,占用额外的内存。 如果 JMath.foo 函数来自其原型,则所有实例共享一个对象。

此外,您可以在事后更改 JMath.prototype.foo,实例将相应更新。 如果您在构造函数中将 foo 函数作为每个实例的方法,那么一旦创建了 JMath 对象,它们就是独立的,并且更改 foo 函数的唯一方法是更改​​每个对象。


编辑2:就只读属性而言,您无法真正从Javascript本身内部实现它们,您需要在表面下进行处理。 但是,您可以声明所谓的“getters”,它实际上充当常量:

JMath.prototype.__defineGetter__("pi2", function() { return Math.PI; });
JMath.prototype.__defineSetter__("pi2", function(){}); // NOP
var j = new JMath();
j.pi2 = 77; // gee, that's nice 
// (if the setter is not defined, you'll get an exception)
j.pi2; // evaluates as Math.PI by calling the getter function

警告:定义 getters/setters 的语法 显然 IE 不能很好地实现< /a>.

Consider using prototype:

function JMath() {};
JMath.prototype = {
    pi2: Math.PI,

    foo: function() {
        return this.pi2;
    }
}

var j = new JMath(); 
j.pi2=44; j.foo(); // returns 44
delete j.pi2; j.foo(); // now returns Math.PI

The difference between this and @altCognito's answer is that here the fields of the object are shared and all point to the same things. If you don't use prototypes, you create new and unlinked instances in the constructor. You can override the prototype's value on a per-instance basis, and if you override it and then decide you don't like the override value and want to restore the original, use delete to remove the override which merely "shadows" the prototype's value.

Edit: if you want to inherit all the methods and fields of the Math object itself, but override some things without affecting the Math object, do something like this (change the name "Constructor1" to your liking):

function Constructor1() {};
Constructor1.prototype = Math;
function JMath() {};
JMath.prototype = new Constructor1();
JMath.prototype.pi2 = JMath.prototype.PI;
JMath.prototype.foo = function() { return this.pi2; }

var j = new JMath();
j.cos(j.foo()); // returns -1

edit 3: explanation for the Constructor1 function: This creates the following prototype chain:

j -> JMath.prototype -> Math

j is an instance of JMath. JMath's prototype is an instance of Constructor1. Constructor1's prototype is Math. JMath.prototype is where the overridden stuff "lives". If you're only implementing a few instances of JMath, you could make the overridden stuff be instance variables that are setup by the constructor JMath, and point directly to Math, like @altCognito's answer does. (j is an instance of JMath and JMath's prototype is Math)

There are 2 downsides of augmenting-an-object-in-the-constructor. (Not actually downsides necessarily) One is that declaring instance fields/methods in the constructor creates separate values for each instance. If you create a lot of instances of JMath, each instance's JMath.foo function will be a separate object taking up additional memory. If the JMath.foo function comes from its prototype, then all the instances share one object.

In addition, you can change JMath.prototype.foo after the fact and the instances will update accordingly. If you make the foo function in the constructor as a per-instance method, then once JMath objects are created, they are independent and the only way to change the foo function is by changing each one.


edit 2: as far as read-only properties go, you can't really implement them from within Javascript itself, you need to muck around under the surface. However you can declare so-called "getters" which effectively act as constants:

JMath.prototype.__defineGetter__("pi2", function() { return Math.PI; });
JMath.prototype.__defineSetter__("pi2", function(){}); // NOP
var j = new JMath();
j.pi2 = 77; // gee, that's nice 
// (if the setter is not defined, you'll get an exception)
j.pi2; // evaluates as Math.PI by calling the getter function

Warning: The syntax for defining getters/setters apparently is not something that IE doesn't implement nicely.

明明#如月 2024-07-23 20:08:07

用户定义的对象属性不能是常量。 Math(和一些其他对象)是一个特殊的内置对象 - 它具有只读属性和函数。 但它不是一个构造函数 - 它只是一个静态对象(Math.constructor === Object)。

而且由于 JavaScript 具有原型继承,而不是经典继承,因此您不能从 Math 继承。 (在此处阅读更多内容

但是,您可以做的是定义原型。 当本地找不到属性时,JS 解析器会在当前对象的原型上查找该属性。 altCognito 当前的解决方案很好地证明了这一点。

我很好奇你到底想要实现什么目标。 也许这样的东西就是你想要的?

var jMath = function()
{
    const pi2 = Math.PI;

    this.getPi2 = function()
    {
        return pi2;
    }
}

var j = new jMath;
alert( j.getPi2() );

User-defined object properties can't be constant. Math (and a few other objects) is a special built-in - it has read-only properties and functions. But it's not a constructor - it's just a static object (Math.constructor === Object).

And because JavaScript has prototypal inheritance, and not classical, you can't inherit from Math. (Read more here)

What you can do, however, is define a prototype. When a property isn't found locally, the JS parser looks for that property on the current object's prototype. altCognito's current solutions shows this very well.

I'm curious about exactly what it is you're trying to achieve. Perhaps something like this is what you want?

var jMath = function()
{
    const pi2 = Math.PI;

    this.getPi2 = function()
    {
        return pi2;
    }
}

var j = new jMath;
alert( j.getPi2() );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文