有没有比写四个基本上做相同事情的函数更好的方法来写这个?我怎么能调用同一个函数,但使用该函数显示同一对象的不同属性呢。
在以下示例中,a
是一个"段落"元素。事件侦听器与类型为button的"input"元素绑定。
function $(id){
return document.querySelector(id);
};
function Person(name, age, weight, favoriteActivity) {
this.name = name;
this.age = age;
this.weight = weight;
this.favoriteActivity = favoriteActivity;
}
var Jack = new Person("Jack Crish", 29, 200, "coding");
var a = document.querySelector("#person");
function showAge(){
a.innerHTML = Jack.age;
}
function showName(){
a.innerHTML = Jack.name;
}
function showWeight(){
a.innerHTML = Jack.weight;
}
function showActivity(){
a.innerHTML = Jack.favoriteActivity;
}
$("#age").addEventListener("click", showAge);
$("#name").addEventListener("click", showName);
$("#weight").addEventListener("click", showWeight);
$("#enjoys").addEventListener("click", showActivity);
JSFiddle在这里找到:http://jsfiddle.net/metkjnyn/
当然,只需让函数接受一个参数,该参数指示要显示的属性。
function $(id){
return document.querySelector(id);
};
function Person(name, age, weight, favoriteActivity) {
this.name = name;
this.age = age;
this.weight = weight;
this.favoriteActivity = favoriteActivity;
}
var Jack = new Person("Jack Crish", 29, 200, "coding");
var a = $("#person");
function showProperty(property) {
this.innerHTML = Jack[property];
}
/*
function showAge(){
a.innerHTML = Jack.age;
}
function showName(){
a.innerHTML = Jack.name;
}
function showWeight(){
a.innerHTML = Jack.weight;
}
function showActivity(){
a.innerHTML = Jack.favoriteActivity;
}
*/
$("#age").addEventListener("click", showProperty.bind(a, 'age'));
$("#name").addEventListener("click", showProperty.bind(a, 'name'));
$("#weight").addEventListener("click", showProperty.bind(a, 'weight'));
$("#enjoys").addEventListener("click", showProperty.bind(a, 'favoriteActivity'));
p{
width:200px;
height:20px;
border:1px solid grey;
}
<p id ="person"></p>
<input id ="age" type = "button" value = "age"></input>
<input id ="name" type = "button" value = "name"></input>
<input id ="weight" type = "button" value = "weight"></input>
<input id ="enjoys" type = "button" value = "enjoys"></input>
由于对象属性可以作为字符串索引访问,并且基于元素的id正是属性名称这一事实,因此可以使用事件调用方的id引用作为要更改的属性:
更新JsFiddle
function show() {
a.innerHTML = Jack[this.id];
}
$("#age").addEventListener("click", show);
$("#name").addEventListener("click", show);
$("#weight").addEventListener("click", show);
$("#enjoys").addEventListener("click", show);
编辑
正如Kevin B所指出的,您需要他们将享受id与实际的属性名称相匹配,如:
http://jsfiddle.net/metkjnyn/4/
<input id ="favoriteActivity" type = "button" value = "enjoys"></input>
$("#favoriteActivity").addEventListener("click", show);
有,但也更糟。例如:
function Person(...) { ...; this.setup(); };
Person.prototype = {
setup: function() {
var self = this;
['name','age','weight','activity'].forEach(function(propName) {
var fname = "show"+propName;
self[fname] = function() { return self[propName]; }
document.getElementById(propName).addEventListener("click", self[fname]);
});
}
};
它更好吗?好吧,是和否。这更简洁,因为它没有重复,所以可能出错的代码更少,但现在你有了一个需要更新的硬编码属性列表,并且你的对象的API几乎和mud一样透明(你现在必须分析代码以找出你的Person对象有什么功能)。
最佳实践是使用易于阅读的API:使对象透明
function Person(name, age, weight, favoriteActivity) {
this.name = name;
this.age = age;
this.weight = weight;
this.favoriteActivity = favoriteActivity;
}
Person.prototype = {
showAge: function(evt){
evt.target.textContent = this.age;
},
showName: function(evt){
evt.target.textContent = this.name;
},
showWeight: function(evt){
evt.target.textContent = this.weight;
},
showActivity: function(evt){
evt.target.textContent = this.favoriteActivity;
},
bindToElement: function(a){
a.querySelector(".name").addEventListener("click", this.showAge);
a.querySelector(".age").addEventListener("click", this.showName);
a.querySelector(".weight").addEventListener("click", this.showWeight);
a.querySelector(".fav").addEventListener("click", this.showActivity);
}
};
然后有一些单独的代码来初始化人员:
function makePerson(name) {
var person = new Person(name);
var el = document.querySelector("....");
person.bindToElement(el);
}
...
makePerson("Jack");
尽量远离那些id
选择器。它们是确保您永远不会在页面中添加其他内容的好方法。
在JavaScript中,您既可以通过Jack.name
格式访问对象的属性,也可以通过Jack['name']
格式访问对象。因此,如果你在每个函数中所做的都是访问给定对象的属性,那么你可以创建一个名为showInfo
的函数,它采用你想要访问的属性的名称:
function showInfo(field) {
a.innerHtml = Jack[field];
}
这样,调用showInfo('name')
将与调用showName()相同。然后,您可以让每个侦听器将一个字符串传递给同一个函数,甚至可能根据按钮的ID来确定这些字符串。希望这能为您指明更好地减少代码重复的方向。
在Person.prototype 中添加一个"get"方法
Person.prototype.get = function (p) {
a.innerHTML = this[p];
}
并在您的eventListener 中调用它
$("input").addEventListener("click", function() {Jack.get(this.value);});
$("#name").addEventListener("click", function() {Jack.get(this.value);});
$("#weight").addEventListener("click", function() {Jack.get(this.value);});
$("#enjoys").addEventListener("click", function() {Jack.get(this.value);});
请参见Fiddle。
您可以创建一个函数来执行事件绑定,并同时指定哪个属性:
function showProperty(id, property) {
$("#" + id).addEventListener("click", function(e) {
a.innerHTML = Jack[property];
});
}
showProperty("age", "age");
showProperty("name", "name");
showProperty("weight", "weight");
showProperty("enjoys", "favoriteActivity");
jsfiddle.net/metkjn/2/
或者,您可以采用更具声明性的方法,并从按钮推断属性。这需要为enjoys
按钮添加一个属性:
<input type="button" value="enjoys" data-property="favoriteActivity" />
function showProperty(e) {
var property = this.getAttribute("data-property") || this.value;
a.innerHTML = Jack[property];
}
var buttons = document.querySelectorAll("input[type=button]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener("click", showProperty);
}
jsfiddle.net/metkjn/5/
两者都比原来的更干燥。