而不是很多事件监听器和函数引用一个对象什么是更好的方法?

时间:2014-11-05 20:50:25

标签: javascript object

有没有更好的方法来编写这个而不是编写四个基本相同的函数?我怎么能调用相同的函数,但使用该函数显示同一对象的不同属性。

在以下示例中,a是“paragraph”元素。 事件监听器与“输入”元素绑定,类型为按钮。

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/

6 个答案:

答案 0 :(得分:2)

当然,只需让函数接受一个指示要显示的属性的参数。

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> 

答案 1 :(得分:1)

由于对象属性可以作为字符串索引访问,并且基于元素的ID正是属性名称这一事实,您可以使用事件调用者的id引用作为要更改的属性:

Updated 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所指出的,你需要它们将 enjoy id与实际的属性名称相匹配,例如:

http://jsfiddle.net/metkjnyn/4/

<input id ="favoriteActivity" type = "button" value = "enjoys"></input> 

$("#favoriteActivity").addEventListener("click", show);

答案 2 :(得分:1)

有,但他们也更糟。例如:

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就像泥一样透明(你现在必须分析代码到找出你的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选择器。它们是确保您无法在页面上添加其他内容的绝佳方式。

答案 3 :(得分:0)

在JavaScript中,您可以通过Jack.name格式以及Jack['name']格式访问对象的属性。因此,如果您在每个函数中执行的操作都是访问给定对象的属性,则可以创建一个名为showInfo的函数,该函数将获取您要访问的属性的名称:

function showInfo(field) {
    a.innerHtml = Jack[field];
}

这样,调用showInfo('name')将与调用showName()相同。然后,您可以让每个侦听器将字符串传递给同一个函数 - 甚至可以根据按钮的ID确定这些字符串。希望这能指导您更好地减少代码重复。

答案 4 :(得分:0)

添加&#34; get&#34;你的Person.prototype的方法

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);});

See Fiddle

答案 5 :(得分:0)

您可以创建一个执行事件绑定的函数,并一次指定哪个属性:

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/metkjnyn/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/metkjnyn/5/

两者都比原来干得多。