Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript:运算符重载_Javascript_Operators_Operator Overloading - Fatal编程技术网

Javascript:运算符重载

Javascript:运算符重载,javascript,operators,operator-overloading,Javascript,Operators,Operator Overloading,我已经使用JavaScript几天了,现在我已经到了一个需要为我定义的对象重载操作符的地步 在谷歌搜索了一段时间后,似乎你还不能正式这么做,但是有一些人声称他们用了一些冗长的方式来完成这个动作 基本上,我制作了一个Vector2类,希望能够完成以下操作: var x = new Vector2(10,10); var y = new Vector2(10,10); x += y; //This does not result in x being a vector with 20,20 as

我已经使用JavaScript几天了,现在我已经到了一个需要为我定义的对象重载操作符的地步

在谷歌搜索了一段时间后,似乎你还不能正式这么做,但是有一些人声称他们用了一些冗长的方式来完成这个动作

基本上,我制作了一个Vector2类,希望能够完成以下操作:

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x += y; //This does not result in x being a vector with 20,20 as its x & y values.
相反,我必须这样做:

var x = new Vector2(10,10);
var y = new Vector2(10,10);

x = x.add(y); //This results in x being a vector with 20,20 as its x & y values. 

在我的Vector2类中有没有一种重载操作符的方法?正如您所发现的,JavaScript不支持运算符重载。最接近的方法是实现
toString
(当需要将实例强制为字符串时将调用该函数)和
valueOf
(例如,当使用
+
进行加法时,或者在许多情况下,当使用它进行串联时,因为
+
尝试在串联之前进行加法),这将被调用以将其强制为数字,这是非常有限的。这两种方法都不允许您创建
矢量2
对象


对于想得到字符串或数字(而不是
Vector2
)的人来说但是,下面是
valueOf
toString
的示例。这些示例没有演示运算符重载,只是利用JavaScript的内置处理转换为原语:

valueOf
此示例将对象的
val
属性的值加倍,以响应被强制到原语的情况,例如通过
+

函数对象(val){
this.val=val;
}
Thing.prototype.valueOf=函数(){
//在这里,我只是加倍它;你实际上会做你的longAdd的事情
返回此值。val*2;
};
var a=新事物(1);
var b=新事物(2);

console.log(a+b);/6(1*2+2*2)
正如T.J.所说,你不能在JavaScript中重载运算符。但是你可以利用
valueOf
函数编写一个hack,它看起来比每次使用
add
之类的函数要好,但是对向量施加了x和y介于0和MAX_值之间的约束。下面是代码:

var MAX_VALUE = 1000000;

var Vector = function(a, b) {
    var self = this;
    //initialize the vector based on parameters
    if (typeof(b) == "undefined") {
        //if the b value is not passed in, assume a is the hash of a vector
        self.y = a % MAX_VALUE;
        self.x = (a - self.y) / MAX_VALUE;
    } else {
        //if b value is passed in, assume the x and the y coordinates are the constructors
        self.x = a;
        self.y = b;
    }

    //return a hash of the vector
    this.valueOf = function() {
        return self.x * MAX_VALUE + self.y;
    };
};

var V = function(a, b) {
    return new Vector(a, b);
};
然后你可以这样写方程:

var a = V(1, 2);            //a -> [1, 2]
var b = V(2, 4);            //b -> [2, 4]
var c = V((2 * a + b) / 2); //c -> [2, 4]

FYI paper.js通过创建PaperScript解决了这个问题,PaperScript是一种自包含的、范围明确的javascript,具有向量的运算符重载,然后将其处理回javascript


但是paperscript文件需要专门指定并进行处理。

实际上,JavaScript有一种变体确实支持运算符重载。ExtendScript是Adobe应用程序(如Photoshop和Illustrator)使用的脚本语言,它确实具有运算符重载。在它中,您可以编写:

Vector2.prototype["+"] = function( b )
{
  return new Vector2( this.x + b.x, this.y + b.y );
}

var a = new Vector2(1,1);
var b = new Vector2(2,2);
var c = a + b;

“Adobe Extendscript JavaScript工具指南”(当前版本)对此进行了更详细的描述。该语法显然是基于ECMAScript标准的一份草案(现已废弃很久)。

可以将两个数字组合成一个数字来进行向量计算。在解释其工作原理之前,让我先展示一个示例:

let a = vec_pack([2,4]);
let b = vec_pack([1,2]);

let c = a+b; // Vector addition
let d = c-b; // Vector subtraction
let e = d*2; // Scalar multiplication
let f = e/2; // Scalar division

console.log(vec_unpack(c)); // [3, 6]
console.log(vec_unpack(d)); // [2, 4]
console.log(vec_unpack(e)); // [4, 8]
console.log(vec_unpack(f)); // [2, 4]

if(a === f) console.log("Equality works");
if(a > b) console.log("Y value takes priority");
我使用的是这样一个事实,如果你将两个数字移位X次,然后在将它们移回之前进行加法或减法运算,你将得到相同的结果,就好像你一开始没有对它们进行移位一样。同样,对于移位的值,标量乘和除法是对称的

一个JavaScript数字有52位整数精度(64位浮点),因此我将把一个数字打包成较高的26位,将一个数字打包成较低的26位。代码变得有点混乱,因为我想支持有符号的数字

function vec_pack(vec){
    return vec[1] * 67108864 + (vec[0] < 0 ? 33554432 | vec[0] : vec[0]);
}

function vec_unpack(number){
    switch(((number & 33554432) !== 0) * 1 + (number < 0) * 2){
        case(0):
            return [(number % 33554432),Math.trunc(number / 67108864)];
        break;
        case(1):
            return [(number % 33554432)-33554432,Math.trunc(number / 67108864)+1];
        break;
        case(2):
            return [(((number+33554432) % 33554432) + 33554432) % 33554432,Math.round(number / 67108864)];
        break;
        case(3):
            return [(number % 33554432),Math.trunc(number / 67108864)];
        break;
    }
}
功能向量包(vec){
返回向量[1]*67108864+(向量[0]<0?33554432 |向量[0]:向量[0]);
}
功能向量解包(编号){
开关(((编号&33554432)!==0)*1+(编号<0)*2){
案例(0):
return[(编号%33554432),Math.trunc(编号/67108864)];
打破
案例(1):
return[(数字%33554432)-33554432,Math.trunc(数字/67108864)+1];
打破
案例(2):
返回[((数字+33554432)%33554432)+33554432)%33554432,数学四舍五入(数字/67108864)];
打破
案例(3):
return[(编号%33554432),Math.trunc(编号/67108864)];
打破
}
}

我能看到的唯一缺点是x和y必须在+-3300万范围内,因为它们必须分别在26位以内。

有趣的是,它也是实验性的
库。它在定义的上下文中进行重载(回调函数)只有。

我们可以使用React-like-hook在每次迭代中使用
valueOf
方法的不同值来计算箭头函数

const a = Vector2(1, 2) // [1, 2]
const b = Vector2(2, 4) // [2, 4]    
const c = Vector2(() => (2 * a + b) / 2) // [2, 4]
// There arrow function will iterate twice
// 1 iteration: method valueOf return X component
// 2 iteration: method valueOf return Y component
常量向量2=(函数(){ 设索引=-1 返回函数(x,y){ 如果(x的类型==='函数'){ 常数计算=x 索引=0,x=calc() 索引=1,y=calc() 索引=-1 } 返回Object.assign([x,y]{ 价值(){ 返回索引==-1?this.toString():this[index] }, toString(){ 返回`[${this[0]},${this[1]}]` }, len(){ 返回Math.sqrt(此[0]**2+此[1]**2) } }) } })() 常数a=Vector2(1,2) 常数b=Vector2(2,4) console.log('a='+a)//a=[1,2] log(`b=${b}`)//b=[2,4] 常数c=Vector2(()=>(2*a+b)/2)/[2,4] a[0]=12 常数d=Vector2(()=>(2*a+b)/2)/[13,4] const normalized=Vector2(()=>d/d.len())/[0.955…,0.294…]
log(c,d,normalized)虽然不是这个问题的确切答案,但是可以使用ES6符号实现一些python神奇的方法

[Symbol.toPrimitive]()
方法不允许您暗示调用
Vector.add()
,但允许您使用诸如
Decimal()+int
之类的语法

class AnswerToLifeAndUniverseAndEverything {
    [Symbol.toPrimitive](hint) {
        if (hint === 'string') {
            return 'Like, 42, man';
        } else if (hint === 'number') {
            return 42;
        } else {
            // when pushed, most classes (except Date)
            // default to returning a number primitive
            return 42;
        }
    }
}
我写了一个库