我已经在Stack Overflow上阅读了一些问题,但我无法找出问题所在。昨天用户Scott Marcus answered对我的问题给出了解释性答案,我使用Object.create()
测试了解决方案,我认为这就是我想写对象的方式。
这是我做过的工作测试:
var Obj = {
/**
* @type {string}
*/
name: '',
uppercase: function () {
this.name = this.name.toUpperCase();
return true;
},
/**
* setName
* Set the `name` property.
*
* @param param
*/
set setName (param) {
this.name = param;
},
get getName () {
return this.name;
}
};
var a = Object.create(Obj);
var b = Object.create(Obj);
a.setName = "Will";
b.setName = "Byers";
console.log("Name in object a is: ".concat(a.getName));
console.log("Name in object b is: ".concat(b.getName));

然后我在我的脚本上尝试了相同的解决方案但Object.create()
这次没有创建两个单独的对象,我无法理解为什么。如果单击CLICK按钮,它会在控制台中打印两个应该不同的对象(对象b
应该只包含 `{asd:" QWE"})但他们实际上是一样的。
任何人都可以解释我的错误吗?
// Declaring my object
var Field = {
/**
* @type {Object}
*/
collection: {},
/**
* collect
* Push the | indexName: value | into collection object.
*
* @param {object} obj
*/
collect: function (obj) {
//console.log(obj);
var indexNames = Object.keys(obj);
var selectors = Object.values(obj);
for (var i=0; i<indexNames.length; i++) {
var el = document.querySelectorAll(selectors[i]);
this.collection[indexNames[i]] = this.fldValue(el);
}
},
/**
* fldValue
* Get the value of the injected object after having recognized its tagName and type.
*
* @param {object} HTMLObject
* @returns {*}
*/
fldValue: function (HTMLObject) {
HTMLObject = HTMLObject[0];
switch (HTMLObject.tagName) {
case "INPUT":
switch (HTMLObject.type) {
case "text":
case "password":
case "hidden":
return HTMLObject.value;
case "checkbox":
return HTMLObject.checked;
default:
throw "Unknown input type: ".concat(HTMLObject.type);
}
case "DIV":
case "P":
case "SPAN":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
return HTMLObject.textContent;
default:
throw "Unknown element tagName: ".concat(HTMLObject.tagName);
}
},
/**
*
* @param {string} className
* @returns {*}
*/
reset: function (className) {
var elements = document.getElementsByClassName(className);
for (var i=0; i<elements.length; i++) {
var el = elements[i];
switch (el.tagName) {
case "INPUT":
switch (el.type) {
case "text":
case "password":
case "hidden":
el.value = '';
break;
case "checkbox":
el.checked = false;
break;
default:
throw "Unknown input type: ".concat(el.type);
}
break;
case "DIV":
case "P":
case "SPAN":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
el.innerHTML = '';
break;
default:
throw "Unknown element: ".concat(el.tagName);
}
}
},
get getCollection() {
return this.collection;
}
};
// --------------------
// Object instantiation
var a = Object.create(Field);
var b = Object.create(Field);
document.getElementById('send')
.addEventListener('click', function (ev) {
a.collect({
name: '[name="name"]',
password: '.password',
title: '.title',
description: '.container',
note: '#paragraph',
chk_1: '[name="chk1"]',
chk_2: '[name="chk2"]'
});
b.collect({
asd: '.title'
});
// !! They should be different but they're actually the same object !!
console.log(a.getCollection);
console.log(b.getCollection);
});
document.getElementById('reset')
.addEventListener('click', function (ev) {
a.reset('reset');
});
&#13;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 class="title">QWE</h1>
<input type="text" class="name reset" name="name">
<input type="password" class="password" name="password">
<input type="checkbox" class="reset" name="chk1">
<input type="checkbox" name="chk2">
<div class="container reset">HEY</div>
<p id="paragraph">OPS</p>
<button id="send">CLICK</button>
<button id="reset">RESET</button>
<script src="Field.js"></script>
<script>
</script>
&#13;
答案 0 :(得分:3)
这是因为collection
是一个对象,由Field
引用,因此a
和b
继承对该单个对象的引用并共享它。最初,在设置Field
之后,你在内存中有这样的东西(省略了很多细节):
+−−−−−−−−−−−−−−−−−−−−−+ Field−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−>| (object) | +−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | collection |−−−>| (object) | | collect |−+ +−−−−−−−−−−+ | ... | | +−−−−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−+ +−>| (function) | +−−−−−−−−−−−−+
然后
var a = Object.create(Field);
var b = Object.create(Field)
你有类似的东西:
+−−−−−−−−−−−−−−−−−−−−−+ Field−−−−−−−−−−−−−−−−−−−−−−−−−−−−+−−+−>| (object) | | | +−−−−−−−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | | | collection |−−−>| (object) | | | | collect |−+ +−−−−−−−−−−+ | | | ... | | | | +−−−−−−−−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−+ | | +−>| (function) | a−−−−−−−−−−−−>| (object) | | | +−−−−−−−−−−−−+ +−−−−−−−−−−−−−−−+ | | | [[Prototype]] |−−+ | +−−−−−−−−−−−−−−−+ | | +−−−−−−−−−−−−−−−+ | b−−−−−−−−−−−−>| (object) | | +−−−−−−−−−−−−−−−+ | | [[Prototype]] |−−−−−+ +−−−−−−−−−−−−−−−+
请注意,a
和b
会继承collection
,这意味着它们会引用相同的集合对象。
相反,您需要a
和b
每个人都拥有拥有 collection
对象:
var a = Object.create(Field);
a.collection = {};
var b = Object.create(Field);
b.collection = {};
// Declaring my object
var Field = {
/**
* @type {Object}
*/
collection: {},
/**
* collect
* Push the | indexName: value | into collection object.
*
* @param {object} obj
*/
collect: function (obj) {
//console.log(obj);
var indexNames = Object.keys(obj);
var selectors = Object.values(obj);
for (var i=0; i<indexNames.length; i++) {
var el = document.querySelectorAll(selectors[i]);
this.collection[indexNames[i]] = this.fldValue(el);
}
},
/**
* fldValue
* Get the value of the injected object after having recognized its tagName and type.
*
* @param {object} HTMLObject
* @returns {*}
*/
fldValue: function (HTMLObject) {
HTMLObject = HTMLObject[0];
switch (HTMLObject.tagName) {
case "INPUT":
switch (HTMLObject.type) {
case "text":
case "password":
case "hidden":
return HTMLObject.value;
case "checkbox":
return HTMLObject.checked;
default:
throw "Unknown input type: ".concat(HTMLObject.type);
}
case "DIV":
case "P":
case "SPAN":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
return HTMLObject.textContent;
default:
throw "Unknown element tagName: ".concat(HTMLObject.tagName);
}
},
/**
*
* @param {string} className
* @returns {*}
*/
reset: function (className) {
var elements = document.getElementsByClassName(className);
for (var i=0; i<elements.length; i++) {
var el = elements[i];
switch (el.tagName) {
case "INPUT":
switch (el.type) {
case "text":
case "password":
case "hidden":
el.value = '';
break;
case "checkbox":
el.checked = false;
break;
default:
throw "Unknown input type: ".concat(el.type);
}
break;
case "DIV":
case "P":
case "SPAN":
case "H1":
case "H2":
case "H3":
case "H4":
case "H5":
case "H6":
el.innerHTML = '';
break;
default:
throw "Unknown element: ".concat(el.tagName);
}
}
},
get getCollection() {
return this.collection;
}
};
// --------------------
// Object instantiation
var a = Object.create(Field);
a.collection = {};
var b = Object.create(Field);
b.collection = {};
document.getElementById('send')
.addEventListener('click', function (ev) {
a.collect({
name: '[name="name"]',
password: '.password',
title: '.title',
description: '.container',
note: '#paragraph',
chk_1: '[name="chk1"]',
chk_2: '[name="chk2"]'
});
b.collect({
asd: '.title'
});
// !! They should be different but they're actually the same object !!
console.log(a.getCollection);
console.log(b.getCollection);
});
document.getElementById('reset')
.addEventListener('click', function (ev) {
a.reset('reset');
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 class="title">QWE</h1>
<input type="text" class="name reset" name="name">
<input type="password" class="password" name="password">
<input type="checkbox" class="reset" name="chk1">
<input type="checkbox" name="chk2">
<div class="container reset">HEY</div>
<p id="paragraph">OPS</p>
<button id="send">CLICK</button>
<button id="reset">RESET</button>
<script src="Field.js"></script>
<script>
</script>
当然,每次创建Field
时都必须编写每个实例的初始化逻辑,这就是为什么我们有构造函数/ class
语法或构建器的原因。如果您不想使用new
,请执行此功能。
function newField() {
var f = Object.create(Field);
f.collection = {};
return f;
}
然后
a = newField();
b = newField();