2016-08-16 3 views
1

Я делаю объект, который получает селектор в качестве аргумента, который имеет один метод с именем stylise, который используется для внесения изменений в CSS выбранного HTML-элемента (ов).Использовать объект напрямую

Код:

/* ----- JavaScript ----- */ 
 
function get(selector) { 
 
    var 
 
     self = {}, 
 
     elements = Array.from(document.querySelectorAll(selector)); 
 
    
 
    this.stylise = function(object) { 
 
     Object.keys(object).forEach(function(propertyName) { 
 
      for (var index = 0; index < elements.length; index++) { 
 
       elements[index].style[propertyName] = object[propertyName]; 
 
      }; 
 
     }); 
 
    }; 
 
    
 
    return Object.setPrototypeOf(self, this.prototype); 
 
};
<!----- HTML -----> 
 
<input id = "text" type = "text" style = "padding: .5em .7em;"/>

Если линия return Object.setPrototypeOf(self, this.prototype); пропускается выше код будет работать, как ожидалось, вызвав это нравится:

var a = new get("#text"); 
a.stylise({ 
    backgroundColor: "yellow", 
    borderRadius: "5px" 
}); 

Однако, Я хочу, чтобы выше работали по телефону это нравится:

get("#text").stylise({ 
    backgroundColor: "yellow", 
    borderRadius: "5px" 
}); 

Я пытался добиться того, чтобы с помощью Object.setPrototypeOf(self, this.prototype), но безуспешно, как я получил следующее сообщение об ошибке в консоли: Object doesn't support property or method 'stylise'.

Какая часть моего кода вызывает это и как я могу это решить?

ответ

5

Вам не нужно setPrototypeOf для этого (есть очень, очень мало ситуаций, когда это то, что вы бы тянуться), просто get возвращает объект, который вы создали, и назначенный self и назначить self.stylise, а не this.stylise :

/* ----- JavaScript ----- */ 
 
function get(selector) { 
 
    var 
 
     self = {}, 
 
     elements = Array.from(document.querySelectorAll(selector)); 
 
    
 
    self.stylise = function(object) { 
 
     Object.keys(object).forEach(function(propertyName) { 
 
      for (var index = 0; index < elements.length; index++) { 
 
       elements[index].style[propertyName] = object[propertyName]; 
 
      }; 
 
     }); 
 
    }; 
 
    
 
    return self; 
 
} 
 
get("#text").stylise({ 
 
    backgroundColor: "yellow", 
 
    borderRadius: "5px" 
 
});
<!----- HTML -----> 
 
<input id = "text" type = "text" style = "padding: .5em .7em;"/>

В самом деле, вы можете создать stylise в пределах инициализатора объекта. Вы можете также использовать forEach на elements:

/* ----- JavaScript ----- */ 
 
function get(selector) { 
 
    var elements = Array.from(document.querySelectorAll(selector)); 
 

 
    return { 
 
    stylise: function(object) { 
 
     Object.keys(object).forEach(function(propertyName) { 
 
     elements.forEach(function(element) { 
 
      element.style[propertyName] = object[propertyName]; 
 
     }); 
 
     }); 
 
    } 
 
    }; 
 
} 
 
get("#text").stylise({ 
 
    backgroundColor: "yellow", 
 
    borderRadius: "5px" 
 
});
<!----- HTML -----> 
 
<input id="text" type="text" style="padding: .5em .7em;" />


Вы сказали, что в другом месте, что вы хотите, чтобы определить stylise вне конструктора (и что положить elements на объекте было хорошо). Если это так, вы делаете это, используя Object.create для создания объекта, поддерживаемого конкретным прототипом объекта (в нашем случае get.prototype); это делает то, что new делает, когда создает объекты перед вызовом конструктора, но вы сказали, что не хотите использовать new.

Обратите внимание, что этот пример сначала создает два объекта через get, а затем вызывает stylise; различные попытки Вас осведомленными, пытаясь сделать это потерпит неудачу в этом сценарии:

/* ----- JavaScript ----- */ 
 

 
// The builder function 
 
function get(selector) { 
 
    // Create a new object we'll return, backed by `get.prototype` 
 
    var obj = Object.create(get.prototype); 
 
    
 
    // Put the elements matching the selector on it 
 
    obj.elements = Array.from(document.querySelectorAll(selector)); 
 
    
 
    // Return it 
 
    return obj; 
 
} 
 

 
// Add `stylise` to the prototype `get` assigns objects 
 
get.prototype.stylise = function(object) { 
 
    // Get our elements, so we don't have to worry about `this` in the callbacks below 
 
    var elements = this.elements; 
 
    
 
    // Style them 
 
    Object.keys(object).forEach(function(propertyName) { 
 
    elements.forEach(function(element) { 
 
     element.style[propertyName] = object[propertyName]; 
 
    }); 
 
    }); 
 
}; 
 

 
// Using it 
 
var t1 = get("#text1"); 
 
var t2 = get("#text2"); 
 
t1.stylise({ 
 
    backgroundColor: "yellow", 
 
    borderRadius: "5px" 
 
}); 
 
t2.stylise({ 
 
    backgroundColor: "green", 
 
    borderRadius: "10px" 
 
});
<!----- HTML -----> 
 
<input id="text1" type="text" style="padding: .5em .7em;" /> 
 
<input id="text2" type="text" style="padding: .5em .7em;" />


Примечание стороны: декларации функции не нужно ; после них (хотя положить один там безвреден). ; предназначен для завершения заявлений. Объявления не являются заявлениями.

+0

Спасибо @ T.J., Ваш ответ отлично работает. Он очень тщательный и дает некоторые приятные альтернативы решению моей проблемы. –

Смежные вопросы