Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
if (this.constructor.name !== 'Calculator') { throw “No way, buddy!”; }
function Calculator() {
if (this.constructor !== Calculator) { throw “No way, buddy!”; }
function Calculator() {
if (! (this instanceof Calculator)) { throw new TypeError(“No way, buddy!”); }
NamedFunction.name = "Good bye";
не сработает, потому как name это readonly-свойство функции.this == null Сенсей, вы не находите, что тогда все три способа тождественны, и ни один из них ни хуже, ни лучше?
var IsInstance = (function () {
return function IsInstance() {
console.log(1);
if (! (this instanceof IsInstance)) throw "No way!";
}
})();
var A = IsInstance;
function IsInstance() {};
var a = new A;
new, ни нацистким способом похачить и без того обернутые в лямбду модули.jQuery('selector', container). Если селектор неправильный, либо такого элемента не существует — вернётся пустой объект jQuery, а не ошибка. И программист, при необходимости, сам проверит есть ли элемент. Тогда вместо кода // Extract jQuery DOM parts from a container using a map of selectors.
priv.extractParts = function (sourceContainer, selectors) {
var domParts = {};
if (!priv.isElement(sourceContainer)) {
throw "POE10: arguments should be 1st — HTML DOM container and 2nd — selectors map";
}
if (!$.isPlainObject(selectors)) {
selectors = {};
}
$.each(selectors, function (name, selector) {
var found,
findMultiple = false;
if (!/^[A-z\.]+$/.test(name)) {
throw "POE12: incorrect selector name `" + name + "`";
}
if ($.isArray(selector) &&
selector.length === 2 &&
$.type(selector[0]) === 'string' &&
$.isFunction(selector[1])) {
domParts[name] = {};
$(sourceContainer).find(selector[0]).each(function () {
var id = selector[1].call(this, this);
if (id) {
if (domParts[name][id]) {
throw "POE13: duplicate identifier `" + id + "` in DOM part namespace `"+ name +"`";
}
domParts[name][id] = this;
}
});
}
else if ($.isPlainObject(selector)) {
domParts[name] = priv.extractParts(sourceContainer, selector);
}
else if (typeof selector === 'string') {
findMultiple = selector.indexOf('[]') === 0;
if (findMultiple) {
selector = selector.replace('[]', '');
}
found = $(sourceContainer).find(selector);
if (found.length === 0) {
throw "POE14: DOM parts weren't found for selector `" + name + "`";
} else if (found.length > 1) {
if (findMultiple) {
found = Array.prototype.slice.call(found);
} else {
throw "POE15: multiple DOM parts found for selector `" + name + "`";
}
} else {
found = found[0];
}
domParts[name] = found;
}
else {
throw "POE16: invalid selector value";
}
});
return domParts;
};
priv.extractParts = function(container, selectors){
var domParts = {};
$.each(selectors, function(name, selector){
domParts[name] = (typeof name == 'string') ?
$(selector, container) : priv.extractParts(container, selector);
});
return domParts;
};
<script type="text/html" id="tmplCalculator">
<table cellspacing="0" cellpadding="0">
<caption><%= caption %></caption>
<tr>
<td colspan="5"><p></p></td>
</tr>
<tr>
<td><input class="calc-button" type="button" value="1"/></td>
<td><input class="calc-button" type="button" value="2"/></td>
<td><input class="calc-button" type="button" value="3"/></td>
<td><input class="calc-button" type="button" value="/"/></td>
<td><input class="calc-func calc-cancel" type="button" title="Cancel" value="C"/></td>
</tr>
<tr>
<td><input class="calc-button" type="button" value="4"/></td>
<td><input class="calc-button" type="button" value="5"/></td>
<td><input class="calc-button" type="button" value="6"/></td>
<td><input class="calc-button" type="button" value="*"/></td>
<td><input class="calc-func calc-undo" type="button" title="Undo" value="←"/></td>
</tr>
<tr>
<td><input class="calc-button" type="button" value="7"/></td>
<td><input class="calc-button" type="button" value="8"/></td>
<td><input class="calc-button" type="button" value="9"/></td>
<td><input class="calc-button" type="button" value="-"/></td>
<td rowspan="2"><input class="calc-func calc-equals" type="button" value="="/></td>
</tr>
<tr>
<td colspan="2"><input class="calc-button calc-0" type="button" value="0"/></td>
<td><input class="calc-button" type="button" value="."/></td>
<td><input class="calc-button" type="button" value="+"/></td>
</tr>
</table>
</script>
;
(function ($) {
function Calculator() {
$.turnToPageObject(this, {
template: $('#tmplCalculator').html(),
containerClass: 'calc',
context: {
caption: "Demo Calculator"
},
selectors: {
"cancel": '.calc-cancel',
"equals": '.calc-equals',
"undo": '.calc-undo',
"led": 'p'
}
});
var history = [],
led = $(this.DOM.led);
$(this.DOM.container).on('click', '.calc-button', function(){
history.push(led.text());
led.append(' ' + $(this).val());
});
$(this.DOM.cancel).click(function(){
history = [];
led.empty();
});
$(this.DOM.equals).click(function(){
history.push(led.text());
try {
led.text((eval(led.text().replace(/ /g, '')) + '').replace(/./g, "$& "));
} catch(e) {
led.text(history.pop());
}
});
$(this.DOM.undo).click(function(){
led.text(history.pop() || '');
});
}
window.Calculator = Calculator;
})(jQuery);
priv.extractParts = function(container, selectors){
var domParts = {};
$.each(selectors, function(name, selector){
domParts[name] = (typeof selector == 'string') ?
$(selector, container) : priv.extractParts(container, selector);
});
return domParts;
};
selectorName: [ realSelector, getKeyFromElementFunction ].1) возвращать не jQuery объекты, а DOM-элементы
2) не допустить невалидные селекторы, чтобы разработчик как-раз не возился с обработкой ошибок
priv.extractParts = function(container, selectors){
var domParts = {};
$.each(selectors, function(name, selector){
if(typeof selector == 'string'){
domParts[name] = $(selector, container);
if(domParts[name].length == 0){
throw 'Incorrect selector "'+selector+'" or element "'+name+'" is not found';
}
} else {
domParts[name] = priv.extractParts(container, selector);
}
});
return domParts;
};
нет фичи selectorName: [ realSelector, getKeyFromElementFunction ]
а чем плохи jQuery объект?Скажу вам, что изначально, когда придумалась
extractParts, она возвращала именно jQ объекты, но постепенно мы пришли к тому, что у этого есть недостатки.$(calc.DOM.container).show() лучше, так как явно указывает человеку, вникающему в код, что вот он обернутый в jQuery дом-элемент.а какой смысл в этой функции?Это инструмент для определенного случая. Например, нужно создать обновляемую таблицу-виджет, столбцы которой — года, а строки — значения метрик.
<script type="text/html" id="tmplTableWidget">
<table>
<tr>
<th></th>
<th>2011</th>
<th>2012</th>
<th>2013</th>
</tr>
<tr data-metric="newUsers">
<th>New Users</th>
<td data-year="2011"></td>
<td data-year="2012"></td>
<td data-year="2013"></td>
</tr>
<tr data-metric="uniqueUsers">
<th>Unique Users</th>
<td data-year="2011"></td>
<td data-year="2012"></td>
<td data-year="2013"></td>
</tr>
<!-- и т.д. -->
</table>
</script>
$.turnToPageObject(this, {
template: $('#tmplTableWidget').html(),
selectors: {
newUsers: [ 'tr[data-metric=newUsers]>td', function () { return $(this).attr('data-year'); } ],
uniqueUsers: [ 'tr[data-metric=uniqueUsers]>td', function () { return $(this).attr('data-year'); } ]
}
});
this.DOM будет выглядет вот так:this.DOM.newUsers.2011
this.DOM.newUsers.2012
this.DOM.newUsers.2013
this.DOM.uniqueUsers.2011
this.DOM.uniqueUsers.2012
this.DOM.uniqueUsers.2013
$(this).find('tr[data-metric='+metric+']>td[data-year='+year+']).text(value) запишем $(this.DOM[metric][year]).text(value), что отработает куда быстрее.
Объекты страницы: описание одной техники