将键/值对象作为参数传递给Javascript构造函数

时间:2016-03-20 12:39:37

标签: javascript oop object parameters constructor

我正在设置一个对象构造函数,并希望将一个键/值对象作为参数传递。我想知道这样做的正确方法是什么?现在我只是将键作为参数传递:

(function() {
    function Venue(name, poor, satisfactory, excellent) {
        this.name = name;
        this.serviceRatings = {
            poor: poor,
            satisfactory: satisfactory,
            excellent: excellent
        };
    }

  var dining = new Venue("dining", .1, .15, .2);

  console.log(dining["serviceRatings"]["satisfactory"] // .15
}());

虽然这是有效的,但是从Ruby背景来看,只有传递对象本身并在初始化程序中分配它的值才感觉正确。这是我能想到的最好的等价物:

class Venue
  def initialize(name, serviceRatings = {})
    @name = name
    @poor = serviceRatings[:poor]
    @satisfactory = serviceRatings[:satisfactory]
    @excellent = serviceRatings[:excellent]
  end
end

有没有办法在Javascript中执行此操作?我现在写东西的方式让我感觉好像我在构造者的参数列表中膨胀(除非 是正确的方法)。

4 个答案:

答案 0 :(得分:2)

你的意思是这样吗?

(function() {
        function Venue(name, serviceRatings) {
            this.name = name;
            this.serviceRatings = serviceRatings;
        }

        var dining = new Venue("dining", {
            poor:.1,
            satisfactory:.15,
            excellent:.2
        });

        console.log(dining["serviceRatings"]["satisfactory"]) // .15
    }());

答案 1 :(得分:2)

您可以像在ruby类中一样传递对象。

function Venue(name, options) {
    this.name = name;
    this.serviceRatings = options;
}

var dining = new Venue("dining",{
        poor: .1,
        satisfactory: .15,
        excellent: .2
    });

以上将创建与以前相同的输出。值得一提的是,ecmascript 2015将类带入了javascript - 所以你也可以这样写:

class Venue {
    constructor(name, options = {}) {
        this.name = name;
        this.serviceRatings = options;
    }
}

上面我们使用空对象作为default parameter,这也是es2015的功能。

如果你想拥有默认的密钥名称,这样的东西就会成为

class Venue {
    constructor(name, options = {}) {
        this.name = name;
        this.serviceRatings = Object.assign({
           poor: undefined,
           satisfactory: undefined,
           excellent: undefined
        }, options);
    }
}

答案 2 :(得分:1)

正如其他人所指出的那样,可以将对象作为参数传递。

// naive ES5 version
function Venue(name, serviceRatings) {
    this.name = name;
    this.serviceRatings = serviceRatings;
}

这种天真的方法存在的问题是JavaScript中的对象是可变的。如果像上面一样分配Object,则可能会意外地改变对象状态。例如:

var ratings = { poor: 0, satisfactory: 2, excellent: 8 };
var diner = new Venue('diner', ratings);

ratings.poor = 12;
var burgerJoint = new Venue('my burgers', ratings);

在这里,您在创建用餐后改变评级,并且您不小心将diner.serviceRatings.poor设置为12。

您可以通过复制对象的值来保护您的代码:

// improved with Object.assign
function Venue(name, serviceRatings) {
    this.name = name;
    this.serviceRatings = Object.assign({}, serviceRatings);
}

Object.assign()将seviceRatings中的每个属性复制到{};这样,以后对其他对象的修改不会影响您的成员属性。

如果您使用的是ES2015,则可以使用对象解构,它具有额外的好处:它可以使您的预期数据结构明确;并允许您指定默认值:

// ES2015 version with explicit parameters and default values
function Venue(name, { poor = 0, satisfactory = 0, excellent = 0 }) {
    this.name = name;
    this.serviceRatings = { poor, satisfactory, excellent };
}

编辑:如另一个答案所示,如果你使用的是ES2015,你可以使用类语法糖:

// ES2015 version using class definition
class Venue
    constructor (name, { poor = 0, satisfactory = 0, excellent = 0 }) {
        this.name = name;
        this.serviceRatings = { poor, satisfactory, excellent };
    }    
}

答案 3 :(得分:0)

参数将包含作为列表传递给函数的所有参数。

(function() {
    function Venue() {
        console.log(arguments);
    }

    var dining = new Venue("dining", .1, .15, .2);

}());