javascript - 在 JavaScript 中使用“持久对象”是一种好习惯吗?
问题描述
根据 Douglas Crockford 的《JavaScript: The Good Parts》一书中的定义,持久对象是一个函数风格的对象,它的所有方法都没有使用this或that。请查看以下示例:
这是持久对象的示例:
const MyObj = function()
{
const myObj = BaseObject();
const inp = create( "input" );
inp.type = "checkbox";
const txt = doc.createTextNode("");
myObj.control = create( "label" );
myObj.control.appendChild( inp );
myObj.control.appendChild( txt );
myObj.setState = state => inp.checked = state;
myObj.getState = () => inp.checked;
myObj.setCaption = cap =>
{
txt.textContent = cap;
}
return myObj;
}
这是非耐用对象的示例:
const MyObj = function()
{
const myObj = BaseObject();
myObj.inp = create( "input" );
myObj.inp.type = "checkbox";
myObj.txt = doc.createTextNode("");
myObj.control = create( "label" );
myObj.control.appendChild( myObj.inp );
myObj.control.appendChild( myObj.txt );
myObj.setState = function(state)
{
this.inp.checked = state; **// Look at here**
}
myObj.getState = function()
{
return this.inp.checked;
}
myObj.setCaption = cap =>
{
this.txt.textContent = cap;
this.callABaseObjectMethode(); **// Look at here**
}
return myObj;
}
我想知道拥有持久对象(this-free)是否是一种好习惯。重要的因素是 JavaScript 代码的性能、安全性、可扩展性和灵活性。
解决方案
你的两个例子都不是很好的例子。
他们俩每次都为方法分配内存。
你myObj
一开始有BaseObject
's 方法、字段。但在你说:allocate memory for setState method and attach to instance
所以来了prototypes
:
MyObj.prototype.setState = state => this._state = state;
MyObj.prototype.getState = () => Object.assign({}, this._state);
原型是静态对象,被分配一次并与类的实例相关联。
现在让我们从您的代码中制作组件(只是为了好玩):
class Component
{
constructor(initialState) {
this._state = initialState ? initialState : {};
this._masterNode = document.createElement(this.constructor.name);
this._eventListeners = {};
}
createElement(tagName, attributes = {}, onStateChange) {
const element = document.createElement(tagName);
Object.assign(element, attributes);
if (onStateChange) {
this.on('stateChanged', (newState) => {
onStateChange(newState, element);
});
}
return element;
}
createInput(name, type, onStateChange) {
return this.createElement('input', {name, type}, onStateChange);
}
createLabel(labelFor, onStateChange) {
return this.createElement('label', {for: labelFor}, onStateChange);
}
createTextNode(text, onStateChange) {
const textNode = document.createTextNode(text);
if (onStateChange) {
this.on('stateChanged', (newState) => {
onStateChange(newState, textNode);
});
}
return textNode;
}
appendChild(element) {
this._masterNode.appendChild(element);
}
setState(state) {
Object.assign(this._state, state);
this.emit('stateChanged', this._state);
}
getState() {
return Object.assign({}, this._state);
}
on(eventName, listener) {
if (!this._eventListeners[eventName]) this._eventListeners[eventName] = [];
this._eventListeners[eventName].push(listener);
}
emit(eventName, payload) {
if (!this._eventListeners[eventName]) return;
console.log(eventName, payload);
this._eventListeners[eventName].forEach(method => {
method(payload);
});
}
appendTo(container) {
container.appendChild(this._masterNode);
}
}
const form = new Component();
// create label
const label = form.createLabel('termsAndConditions');
// create checkbox with state listener
const checkbox = form.createInput('something', 'checkbox',
(newState, element) => {
if (newState.agreedWithTC === true) {
element.checked = true;
return;
}
element.checked = false;
});
// operating with state on click by checkbox
checkbox.onclick = () => {
if (checkbox.checked) {
form.setState({agreedWithTC: true});
return;
}
form.setState({agreedWithTC: false});
};
// append checkbox to label
label.appendChild(checkbox);
const textNode = form.createTextNode('Agree with T&C',
(newState, element) => {
textNode.textContent = textNode.textContent.replace('(agreed)', '').replace('(not agreed)', '');
if (newState.agreedWithTC === true) {
textNode.textContent += ' (agreed)';
return;
}
textNode.textContent += ' (not agreed)';
});
// create text node and append it to label
label.appendChild(textNode);
// append label to form
form.appendChild(label);
// append overall component instance to container
form.appendTo(document.getElementById('container'));
setInterval(() => {
form.setState({agreedWithTC: !form.getState().agreedWithTC});
}, 1000);
<div id="container"></div>
推荐阅读
- docker - Docker - Kibana、APM、Elasticsearch 问题 -
- c++ - 我收到错误“矩阵”类型的无效操作数
*' 和 'int' 到二进制 'operator*' - java - 如何在java中提取双引号之间的字符串?
- c# - 如何从第三种形式将表单打开到面板中?
- c# - 为什么我的模型属性在尝试 POST 时为空?
- python - 尝试检测人脸时网络摄像头窗口总是崩溃
- python - Django gettext 和 gettext_lazy 都以相同的名称导入
- android - 三星设备上的位图存储已像素化,无法在文件夹中找到。仅在设备重启后修复
- java - 我的通用方法不适用于参数
- sql - 如何在 Apache Drill 中获取更多错误详情