JavaScript 元组中的变量赋值

发布于 2024-10-08 23:39:05 字数 532 浏览 4 评论 0原文

在 Python 2 和 Python 3 等其他语言中,您可以定义元组变量并将值分配给元组变量,然后像这样检索它们的值:

tuple = ("Bob", 24)
name, age = tuple
print(name)           #name evaluates to Bob
print(age)            #age evaluates to 24

JavaScript 中有类似的东西吗?或者我是否必须用数组以丑陋的方式做到这一点:

tuple = ["Bob", 24]
name = tuple[0]       //name Evaluates to Bob
age = tuple[1]        //age Evaluates to 24

是否有更好的方法在 JavaScript 5 中模拟 Python 元组?

更新:请参阅有关 ES6 的答案,对于新项目来说,ES6 应该比 CoffeeScript 更受青睐。

In other languages like Python 2 and Python 3, you can define and assign values to a tuple variable, and retrieve their values like this:

tuple = ("Bob", 24)
name, age = tuple
print(name)           #name evaluates to Bob
print(age)            #age evaluates to 24

Is there anything similar in JavaScript? Or do I just have to do it the ugly way with an array:

tuple = ["Bob", 24]
name = tuple[0]       //name Evaluates to Bob
age = tuple[1]        //age Evaluates to 24

Is there a better way to simulate Python tuples in JavaScript 5?

Update: See the answer regarding ES6, which should be favored over CoffeeScript for new projects.

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

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

发布评论

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

评论(12

一指流沙 2024-10-15 23:39:05

JavaScript 1.7 添加了解构赋值语法,它允许你基本上要做你想做的事:

function getTuple(){
   return ["Bob", 24];
}
var [a, b] = getTuple();
// a === "bob" , b === 24 are both true

JavaScript 1.7 added destructuring assignment syntax which allows you to do essentially what you are after:

function getTuple(){
   return ["Bob", 24];
}
var [a, b] = getTuple();
// a === "bob" , b === 24 are both true
挽清梦 2024-10-15 23:39:05

你必须以丑陋的方式去做。如果您真的想要这样的东西,您可以查看CoffeeScript,它有这个和一个还有很多其他功能使它看起来更像 python(抱歉让它听起来像广告,但我真的很喜欢它。)

You have to do it the ugly way. If you really want something like this, you can check out CoffeeScript, which has that and a whole lot of other features that make it look more like python (sorry for making it sound like an advertisement, but I really like it.)

≈。彩虹 2024-10-15 23:39:05

您可以执行类似的操作:

var tuple = Object.freeze({ name:'Bob', age:14 })

然后将名称和年龄引用为属性

tuple.name 
tuple.age 

You can do something similar:

var tuple = Object.freeze({ name:'Bob', age:14 })

and then refer to name and age as attributes

tuple.name 
tuple.age 
月寒剑心 2024-10-15 23:39:05

这种“元组”功能在 EcmaScript2015 中称为解构,并且很快就会受到最新浏览器的支持。目前,只有 Firefox 和 Chrome 支持

但是,嘿,您可以使用 转译器

代码看起来和 python 一样漂亮:

let tuple = ["Bob", 24]
let [name, age] = tuple

console.log(name)
console.log(age)

This "tuple" feature it is called destructuring in EcmaScript2015 and is soon to be supported by up to date browsers. For the time being, only Firefox and Chrome support it.

But hey, you can use a transpiler.

The code would look as nice as python:

let tuple = ["Bob", 24]
let [name, age] = tuple

console.log(name)
console.log(age)
冧九 2024-10-15 23:39:05

冻结数组的行为与 python 元组相同:

const tuple = Object.freeze(["Bob", 24]);
let [name, age]; = tuple
console.debug(name); // "Bob"
console.debug(age); // 24

花哨并定义一个类

class Tuple extends Array { 
  constructor(...items) { 
    super(...items); 
    Object.freeze(this);
  } 
}

let tuple = new Tuple("Jim", 35);
let [name, age] = tuple;
console.debug(name); // Jim
console.debug(age); // 35
tuple = ["Bob", 24]; // no effect 
console.debug(name); // Jim
console.debug(age); // 25

现在可以在所有最新的浏览器中使用。

A frozen array behaves identically to a python tuple:

const tuple = Object.freeze(["Bob", 24]);
let [name, age]; = tuple
console.debug(name); // "Bob"
console.debug(age); // 24

Be fancy and define a class

class Tuple extends Array { 
  constructor(...items) { 
    super(...items); 
    Object.freeze(this);
  } 
}

let tuple = new Tuple("Jim", 35);
let [name, age] = tuple;
console.debug(name); // Jim
console.debug(age); // 35
tuple = ["Bob", 24]; // no effect 
console.debug(name); // Jim
console.debug(age); // 25

Works today in all the latest browsers.

桃酥萝莉 2024-10-15 23:39:05

JavaScript 不支持元组

如果您正在寻找不可变列表,可以使用 Object.freeze() 使数组不可变。

Object.freeze() 方法冻结对象:即阻止向其添加新属性;防止现有属性被删除;并防止现有属性或其可枚举性、可配置性或可写性被更改。本质上,对象实际上是不可变的。该方法返回被冻结的对象。

来源:Mozilla 开发者网络 - 对象。 freeze()

照常分配一个数组,但使用“Object.freeze()”锁定它

> tuple = Object.freeze(['Bob', 24]);
[ 'Bob', 24 ]

像使用常规数组一样使用这些值(python 多重赋值)不支持)

> name = tuple[0]
'Bob'
> age = tuple[1]
24

尝试分配新值

> tuple[0] = 'Steve'
'Steve'

但值未更改

> console.log(tuple)
[ 'Bob', 24 ]

Tuples aren't supported in JavaScript

If you're looking for an immutable list, Object.freeze() can be used to make an array immutable.

The Object.freeze() method freezes an object: that is, prevents new properties from being added to it; prevents existing properties from being removed; and prevents existing properties, or their enumerability, configurability, or writability, from being changed. In essence the object is made effectively immutable. The method returns the object being frozen.

Source: Mozilla Developer Network - Object.freeze()

Assign an array as usual but lock it using 'Object.freeze()

> tuple = Object.freeze(['Bob', 24]);
[ 'Bob', 24 ]

Use the values as you would a regular array (python multi-assignment is not supported)

> name = tuple[0]
'Bob'
> age = tuple[1]
24

Attempt to assign a new value

> tuple[0] = 'Steve'
'Steve'

But the value is not changed

> console.log(tuple)
[ 'Bob', 24 ]
雪若未夕 2024-10-15 23:39:05

不幸的是,您不能在 (ECMA|Java)Script 中使用该元组赋值语法。

编辑:有人链接到 Mozilla/JS 1.7 - 这不能跨浏览器工作,但如果不需要,那么这就是你的答案。

Unfortunately you can't use that tuple assignment syntax in (ECMA|Java)Script.

EDIT: Someone linked to Mozilla/JS 1.7 - this wouldn't work cross-browser but if that is not required then there's your answer.

原野 2024-10-15 23:39:05

这并不是为了在现实生活中实际使用,只是一个有趣的练习。请参阅 为什么使用 JavaScript eval 函数是一个坏主意? 了解详情。

这是您无需求助于特定于供应商的扩展即可获得的最接近的结果:

myArray = [1,2,3];
eval(set('a,b,c = myArray'));

辅助函数:

function set(code) {
    var vars=code.split('=')[0].trim().split(',');
    var array=code.split('=')[1].trim();
    return 'var '+vars.map(function(x,i){return x+'='+array+'['+i+']'}).join(',');
}

证明它可以在任意范围内工作:

(function(){
    myArray = [4,5,6];
    eval(set('x,y,z = myArray'));
    console.log(y);  // prints 5
})()

Safari 不支持 eval

This is not intended to be actually used in real life, just an interesting exercise. See Why is using the JavaScript eval function a bad idea? for details.

This is the closest you can get without resorting to vendor-specific extensions:

myArray = [1,2,3];
eval(set('a,b,c = myArray'));

Helper function:

function set(code) {
    var vars=code.split('=')[0].trim().split(',');
    var array=code.split('=')[1].trim();
    return 'var '+vars.map(function(x,i){return x+'='+array+'['+i+']'}).join(',');
}

Proof that it works in arbitrary scope:

(function(){
    myArray = [4,5,6];
    eval(set('x,y,z = myArray'));
    console.log(y);  // prints 5
})()

eval is not supported in Safari.

和影子一齐双人舞 2024-10-15 23:39:05

作为部长答案的更新,您现在可以使用 es2015 执行此操作:

function Tuple(...args) {
  args.forEach((val, idx) => 
    Object.defineProperty(this, "item"+idx, { get: () => val })
  )
}


var t = new Tuple("a", 123)
console.log(t.item0) // "a"
t.item0 = "b"
console.log(t.item0) // "a"

https://jsbin.com /fubaluwimo/edit?js,控制台

As an update to The Minister's answer, you can now do this with es2015:

function Tuple(...args) {
  args.forEach((val, idx) => 
    Object.defineProperty(this, "item"+idx, { get: () => val })
  )
}


var t = new Tuple("a", 123)
console.log(t.item0) // "a"
t.item0 = "b"
console.log(t.item0) // "a"

https://jsbin.com/fubaluwimo/edit?js,console

给妤﹃绝世温柔 2024-10-15 23:39:05

您也可以在 Javascript 中使用元组类型。用高阶函数定义就可以了(学术术语是Church编码):

const Tuple = (...args) => {
  const Tuple = f => f(...args);
  return Object.freeze(Object.assign(Tuple, args));
};

const get1 = tx => tx((x, y) => x);

const get2 = tx => tx((x, y) => y);

const bimap = f => g => tx => tx((x, y) => Tuple(f(x), g(y)));

const toArray = tx => tx((...args) => args);

// aux functions

const inc = x => x + 1;
const toUpperCase = x => x.toUpperCase();

// mock data

const pair = Tuple(1, "a");

// application

console.assert(get1(pair) === 1);
console.assert(get2(pair) === "a");

const {0:x, 1:y} = pair;
console.log(x, y); // 1 a

console.log(toArray(bimap(inc) (toUpperCase) (pair))); // [2, "A"]

const map = new Map([Tuple(1, "a"), Tuple(2, "b")]);
console.log(map.get(1), map.get(2)); // a b

请注意,Tuple 不用作普通构造函数。该解决方案根本不依赖于原型系统,而仅依赖于高阶函数。

与像元组一样使用的Array相比,元组有哪些优点? Church 编码的元组在设计上是不可变的,因此可以防止突变引起的副作用。这有助于构建更强大的应用程序。此外,更容易推理区分作为集合类型的Array(例如[a])和作为各种类型的相关数据的元组(例如>(a, b))。

You can have a tuple type in Javascript as well. Just define it with higher order functions (the academic term is Church encoding):

const Tuple = (...args) => {
  const Tuple = f => f(...args);
  return Object.freeze(Object.assign(Tuple, args));
};

const get1 = tx => tx((x, y) => x);

const get2 = tx => tx((x, y) => y);

const bimap = f => g => tx => tx((x, y) => Tuple(f(x), g(y)));

const toArray = tx => tx((...args) => args);

// aux functions

const inc = x => x + 1;
const toUpperCase = x => x.toUpperCase();

// mock data

const pair = Tuple(1, "a");

// application

console.assert(get1(pair) === 1);
console.assert(get2(pair) === "a");

const {0:x, 1:y} = pair;
console.log(x, y); // 1 a

console.log(toArray(bimap(inc) (toUpperCase) (pair))); // [2, "A"]

const map = new Map([Tuple(1, "a"), Tuple(2, "b")]);
console.log(map.get(1), map.get(2)); // a b

Please note that Tuple isn't used as a normal constructor. The solution doesn't rely on the prototype system at all, but solely on higher order functions.

What are the advantages of tuples over Arrays used like tuples? Church encoded tuples are immutable by design and thus prevent side effects caused by mutations. This helps to build more robust applications. Additionally, it is easier to reason about code that distinguishes between Arrays as a collection type (e.g. [a]) and tuples as related data of various types (e.g. (a, b)).

铜锣湾横着走 2024-10-15 23:39:05

这是一个简单的 Javascript 元组实现:

var Tuple = (function () {
   function Tuple(Item1, Item2) {
      var item1 = Item1;
      var item2 = Item2;
      Object.defineProperty(this, "Item1", {
          get: function() { return item1  }
      });
      Object.defineProperty(this, "Item2", {
          get: function() { return item2  }
      });
   }
   return Tuple;
})();

var tuple = new Tuple("Bob", 25); // Instantiation of a new Tuple
var name = tuple.Item1; // Assignment. name will be "Bob"
tuple.Item1 = "Kirk"; // Will not set it. It's immutable.

这是一个 2 元组,但是,您可以修改我的示例以支持 3、4、5、6 等元组。

Here is a simple Javascript Tuple implementation:

var Tuple = (function () {
   function Tuple(Item1, Item2) {
      var item1 = Item1;
      var item2 = Item2;
      Object.defineProperty(this, "Item1", {
          get: function() { return item1  }
      });
      Object.defineProperty(this, "Item2", {
          get: function() { return item2  }
      });
   }
   return Tuple;
})();

var tuple = new Tuple("Bob", 25); // Instantiation of a new Tuple
var name = tuple.Item1; // Assignment. name will be "Bob"
tuple.Item1 = "Kirk"; // Will not set it. It's immutable.

This is a 2-tuple, however, you could modify my example to support 3,4,5,6 etc. tuples.

绅士风度i 2024-10-15 23:39:05

我做了一个效果很好的元组实现。该解决方案允许数组解构以及基本类型检查。

const Tuple = (function() {
    function Tuple() {
        // Tuple needs at least one element
        if (arguments.length < 1) {
            throw new Error('Tuple needs at least one element');
        }

        const args = { ...arguments };

        // Define a length property (equal to the number of arguments provided)
        Object.defineProperty(this, 'length', {
            value: arguments.length,
            writable: false
        });

        // Assign values to enumerable properties
        for (let i in args) {
            Object.defineProperty(this, i, {
                enumerable: true,
                get() {
                    return args[+i];
                },
                // Checking if the type of the provided value matches that of the existing value
                set(value) {
                    if (typeof value !== typeof args[+i]) {
                        throw new Error('Cannot assign ' + typeof value + ' on ' + typeof args[+i]);
                    }

                    args[+i] = value;
                }
            });
        }

        // Implementing iteration with Symbol.iterator (allows for array destructuring as well for...of loops)
        this[Symbol.iterator] = function() {
            const tuple = this;

            return {
                current: 0,
                last: tuple.length - 1,
                next() {
                    if (this.current <= this.last) {
                        let val = { done: false, value: tuple[this.current] };
                        this.current++;
                        return val;
                    } else {
                        return { done: true };
                    }
                }
            };
        };

        // Sealing the object to make sure no more values can be added to tuple
        Object.seal(this);
    }

    // check if provided object is a tuple
    Tuple.isTuple = function(obj) {
        return obj instanceof Tuple;
    };

    // Misc. for making the tuple more readable when printing to the console
    Tuple.prototype.toString = function() {
        const copyThis = { ...this };
        const values = Object.values(copyThis);
        return `(${values.join(', ')})`;
    };

    // conctat two instances of Tuple
    Tuple.concat = function(obj1, obj2) {
        if (!Tuple.isTuple(obj1) || !Tuple.isTuple(obj2)) {
            throw new Error('Cannot concat Tuple with ' + typeof (obj1 || obj2));
        }

        const obj1Copy = { ...obj1 };
        const obj2Copy = { ...obj2 };

        const obj1Items = Object.values(obj1Copy);
        const obj2Items = Object.values(obj2Copy);

        return new Tuple(...obj1Items, ...obj2Items);
    };

    return Tuple;
})();

const SNAKE_COLOR = new Tuple(0, 220, 10);

const [red, green, blue] = SNAKE_COLOR;
console.log(green); // => 220


I made a tuple implementation that works quite well. This solution allows for array destructuring, as well as basic type-cheking.

const Tuple = (function() {
    function Tuple() {
        // Tuple needs at least one element
        if (arguments.length < 1) {
            throw new Error('Tuple needs at least one element');
        }

        const args = { ...arguments };

        // Define a length property (equal to the number of arguments provided)
        Object.defineProperty(this, 'length', {
            value: arguments.length,
            writable: false
        });

        // Assign values to enumerable properties
        for (let i in args) {
            Object.defineProperty(this, i, {
                enumerable: true,
                get() {
                    return args[+i];
                },
                // Checking if the type of the provided value matches that of the existing value
                set(value) {
                    if (typeof value !== typeof args[+i]) {
                        throw new Error('Cannot assign ' + typeof value + ' on ' + typeof args[+i]);
                    }

                    args[+i] = value;
                }
            });
        }

        // Implementing iteration with Symbol.iterator (allows for array destructuring as well for...of loops)
        this[Symbol.iterator] = function() {
            const tuple = this;

            return {
                current: 0,
                last: tuple.length - 1,
                next() {
                    if (this.current <= this.last) {
                        let val = { done: false, value: tuple[this.current] };
                        this.current++;
                        return val;
                    } else {
                        return { done: true };
                    }
                }
            };
        };

        // Sealing the object to make sure no more values can be added to tuple
        Object.seal(this);
    }

    // check if provided object is a tuple
    Tuple.isTuple = function(obj) {
        return obj instanceof Tuple;
    };

    // Misc. for making the tuple more readable when printing to the console
    Tuple.prototype.toString = function() {
        const copyThis = { ...this };
        const values = Object.values(copyThis);
        return `(${values.join(', ')})`;
    };

    // conctat two instances of Tuple
    Tuple.concat = function(obj1, obj2) {
        if (!Tuple.isTuple(obj1) || !Tuple.isTuple(obj2)) {
            throw new Error('Cannot concat Tuple with ' + typeof (obj1 || obj2));
        }

        const obj1Copy = { ...obj1 };
        const obj2Copy = { ...obj2 };

        const obj1Items = Object.values(obj1Copy);
        const obj2Items = Object.values(obj2Copy);

        return new Tuple(...obj1Items, ...obj2Items);
    };

    return Tuple;
})();

const SNAKE_COLOR = new Tuple(0, 220, 10);

const [red, green, blue] = SNAKE_COLOR;
console.log(green); // => 220


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