Javascript 构建器模式看不到声明的变量
Javascript Builder Pattern Not Seeing Declared Varialble
我正在尝试实施构建器模式以生成 JSON 选项字符串,这些选项被传递到库中以生成小部件。我不明白为什么 console.log 下面的 this.options 是未定义的。
let Options = function(options) {
this.options = options;
}
let OptionsObjectBuilder = function () {
let options;
return {
addConstantLineToValueAxis: function (lineValue) {
console.log(this.options); // EQUALS UNDEFINED SO CAN'T ADD TO THIS OBJECT
this.options.valueAxis.constantLine.value = lineValue;
return this;
},
build: function () {
return new Options(this.options);
}
};
};
let option = new OptionsObjectBuilder().addConstantLineToValueAxis(1000000000).build();
我相信我应该只在构建器模式中的添加函数末尾返回时使用 this
。我仍然不确定为什么在示例 (zetcode.com/javascript/builderpattern) 中我的代码基于.. 他们使用 this.name
设置值,但在他们的构建函数中传递了 name
。
// @Steven de Salas: expando function:
function buildObjectDepth(obj, base) {
return Object.keys(obj)
.reduce((clone, key) => {
key.split('.').reduce((innerObj, innerKey, i, arr) =>
innerObj[innerKey] = (i+1 === arr.length) ? obj[key] : innerObj[innerKey] || {}, clone)
return clone;
}, Object.assign({}, base));
}
let Options = function(options) {
this.options = options;
}
let OptionsObjectBuilder = function () {
let options = {};
return {
addConstantLineToValueAxis: function (lineValue) {
options = buildObjectDepth({"valueAxis.constantLine.value": lineValue}, options);
return this;
},
build: function () {
return new Options(options);
}
};
};
let obj = new OptionsObjectBuilder().addConstantLineToValueAxis(1000000000).build();
str = JSON.stringify(obj);
str = JSON.stringify(obj, null, 4); // indented output.
alert(str);
构建器有两种不同的方式来存储临时状态:
- 在构建器对象本身中(通过设置
this.options =
)
- 在闭包中(通过设置
options =
)
闭包示例的好处是外部无法访问临时构建器状态。
您可以使用任何一种方式,只要建造者从正确的地方使用它们。我将修复您提到的 post 中的损坏示例。我认为他们开始使用闭包,但它没有用,因为参数名称隐藏了闭包变量,他们最终在切换到使用 this
时感到困惑。他们忘记更新 build()
函数以从正确的位置读取。
使用构建器对象状态 - 公开内部状态
let Task = function(name, description, finished, dueDate) {
this.name = name;
this.description = description;
this.finished = finished;
this.dueDate = dueDate;
}
let TaskBuilder = function () {
return {
setName: function (name) {
this.name = name;
return this;
},
setDescription: function (description) {
this.description = description;
return this;
},
setFinished: function (finished) {
this.finished = finished;
return this;
},
setDueDate: function (dueDate) {
this.dueDate = dueDate;
return this;
},
build: function () {
return new Task(this.name, this.description, this.isFinished, this.dueDate);
}
};
};
let builder = new TaskBuilder().setName('Task A').setDescription('finish book')
.setDueDate(new Date(2019, 5, 12));
let task = builder.build();
// Notice the builder does expose the name/description... properties
console.log({builder, task});
使用闭包变量 - 隐藏内部状态
let Task = function(name, description, finished, dueDate) {
this.name = name;
this.description = description;
this.finished = finished;
this.dueDate = dueDate;
}
let TaskBuilder = function () {
let name;
let description;
let isFinished = false;
let dueDate;
return {
setName: function (pName) {
name = pName;
return this;
},
setDescription: function (pDescription) {
description = pDescription;
return this;
},
setFinished: function (pFinished) {
finished = pFinished;
return this;
},
setDueDate: function (pDueDate) {
dueDate = pDueDate;
return this;
},
build: function () {
return new Task(name, description, isFinished, dueDate);
}
};
};
let builder = new TaskBuilder().setName('Task A').setDescription('finish book')
.setDueDate(new Date(2019, 5, 12));
let task = builder.build();
// Can't see the name/description... properties on the builder, just the methods
console.log({builder, task});
我正在尝试实施构建器模式以生成 JSON 选项字符串,这些选项被传递到库中以生成小部件。我不明白为什么 console.log 下面的 this.options 是未定义的。
let Options = function(options) {
this.options = options;
}
let OptionsObjectBuilder = function () {
let options;
return {
addConstantLineToValueAxis: function (lineValue) {
console.log(this.options); // EQUALS UNDEFINED SO CAN'T ADD TO THIS OBJECT
this.options.valueAxis.constantLine.value = lineValue;
return this;
},
build: function () {
return new Options(this.options);
}
};
};
let option = new OptionsObjectBuilder().addConstantLineToValueAxis(1000000000).build();
我相信我应该只在构建器模式中的添加函数末尾返回时使用 this
。我仍然不确定为什么在示例 (zetcode.com/javascript/builderpattern) 中我的代码基于.. 他们使用 this.name
设置值,但在他们的构建函数中传递了 name
。
// @Steven de Salas: expando function:
function buildObjectDepth(obj, base) {
return Object.keys(obj)
.reduce((clone, key) => {
key.split('.').reduce((innerObj, innerKey, i, arr) =>
innerObj[innerKey] = (i+1 === arr.length) ? obj[key] : innerObj[innerKey] || {}, clone)
return clone;
}, Object.assign({}, base));
}
let Options = function(options) {
this.options = options;
}
let OptionsObjectBuilder = function () {
let options = {};
return {
addConstantLineToValueAxis: function (lineValue) {
options = buildObjectDepth({"valueAxis.constantLine.value": lineValue}, options);
return this;
},
build: function () {
return new Options(options);
}
};
};
let obj = new OptionsObjectBuilder().addConstantLineToValueAxis(1000000000).build();
str = JSON.stringify(obj);
str = JSON.stringify(obj, null, 4); // indented output.
alert(str);
构建器有两种不同的方式来存储临时状态:
- 在构建器对象本身中(通过设置
this.options =
) - 在闭包中(通过设置
options =
)
闭包示例的好处是外部无法访问临时构建器状态。
您可以使用任何一种方式,只要建造者从正确的地方使用它们。我将修复您提到的 post 中的损坏示例。我认为他们开始使用闭包,但它没有用,因为参数名称隐藏了闭包变量,他们最终在切换到使用 this
时感到困惑。他们忘记更新 build()
函数以从正确的位置读取。
使用构建器对象状态 - 公开内部状态
let Task = function(name, description, finished, dueDate) {
this.name = name;
this.description = description;
this.finished = finished;
this.dueDate = dueDate;
}
let TaskBuilder = function () {
return {
setName: function (name) {
this.name = name;
return this;
},
setDescription: function (description) {
this.description = description;
return this;
},
setFinished: function (finished) {
this.finished = finished;
return this;
},
setDueDate: function (dueDate) {
this.dueDate = dueDate;
return this;
},
build: function () {
return new Task(this.name, this.description, this.isFinished, this.dueDate);
}
};
};
let builder = new TaskBuilder().setName('Task A').setDescription('finish book')
.setDueDate(new Date(2019, 5, 12));
let task = builder.build();
// Notice the builder does expose the name/description... properties
console.log({builder, task});
使用闭包变量 - 隐藏内部状态
let Task = function(name, description, finished, dueDate) {
this.name = name;
this.description = description;
this.finished = finished;
this.dueDate = dueDate;
}
let TaskBuilder = function () {
let name;
let description;
let isFinished = false;
let dueDate;
return {
setName: function (pName) {
name = pName;
return this;
},
setDescription: function (pDescription) {
description = pDescription;
return this;
},
setFinished: function (pFinished) {
finished = pFinished;
return this;
},
setDueDate: function (pDueDate) {
dueDate = pDueDate;
return this;
},
build: function () {
return new Task(name, description, isFinished, dueDate);
}
};
};
let builder = new TaskBuilder().setName('Task A').setDescription('finish book')
.setDueDate(new Date(2019, 5, 12));
let task = builder.build();
// Can't see the name/description... properties on the builder, just the methods
console.log({builder, task});