class Main {
constructor(public name: string) {}
}
class Sub extends Main {
constructor(name: string, public lastname: string) {
super(name)
}
}
const sub = new Sub('michael', 'jackson')
function hello (person: Main) {
console.log(person.name)
if(person instanceof Sub) {
console.log(person.lastname)
}
}
hello(sub)
console.log
не вызывает неявного приведения к строке, а потому в консоли мы увидим не 8
, а то что там и есть на самом деле, т.е. function inner() {}
toString
же неявно вызывается именно в случае использования объекта как строки. console.log(sum(1)(2)(2)(3) + 'px') // 8px
.interface Dictionary<T> {
[key: string]: T
}
function serialize<T extends Dictionary<string | number[]>> (arg: T) {
var res = '';
var replaceNamePop: Dictionary<string> = {
modules: 'module',
categories: 'category',
searchFieldsList: 'searchFieldList'
};
Object.keys(arg).forEach(function (this: T, key) {
if (Array.isArray(this[key])) {
for (var j = 0; j < this[key].length; j++) {
if (typeof replaceNamePop[key] != 'undefined')
res += '&' + replaceNamePop[key] + '=' + this[key][j];
else
res += '&' + key + '=' + this[key][j];
}
} else {
if (typeof replaceNamePop[key] != 'undefined')
res += '&' + replaceNamePop[key] + '=' + this[key];
else
res += '&' + key + '=' + this[key];
}
}, arg);
return res;
}
serialize({
'modules': [20],
'categories': [20],
'keyword': 'keyword',
'time': 'time',
'catRelation': 'cat',
'sortField': 'sort',
'sortDirection': 'ASC',
'searchFieldsList': 'list'
});
serialize({
'modules': [20, 25],
'categories': [20, 58],
'keyword': 'keyword',
'time': 'time',
'catRelation': 'cat',
'sortField': 'sort',
'sortDirection': 'ASC',
'searchFieldsList': 'list'
});
serialize({
'modules': [20, 25],
'keyword': 'keyword'
});
var app = new Vue({
el: '#vue-app-one',
data: {
sitename: 'The Shop',
string: 'Hello',
product: {
id: 1001,
title: 'Phone',
description: 'The best one <em>phone</em> ever',
price: 1000000,
image: 'This is an image',
},
filters: {
formatPrice: function(price){
if (!parseInt(price)) {return "";}
if (price > 9999){
var priceString = (price /100).toFixed(2);
var priceArray = priceString.split("").reverse();
var index = 3;
while (priceArray.length > index +3){
priceArray.splice(index+3, 0, ',');
index +=4;
}
return '$' + priceArray.reverse().join('');
} else{
return '$' + (price/100).toFixed(2);
}
}
}
},
});
Ничего не замечаете?head
и прочие body
.XMLHttpRequest
вызывает событие readystatechange\onprogress
несколько раз с промежуточными результатами, а также имеет метод abort
для остановки. Однако с современными скоростями интернета весь контент скорее всего будет загружен быстрее чем браузер сможет остановить зарос.function parseHead(text) {
if(!parseHead.parser)
parseHead.parser = new DOMParser();
return parseHead.parser.parseFromString(
text.match(/<head>[\s\S]*?<\/head>/i)[0],
"text/html"
).head;
}
function getHead(url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function(event) {
if (xhr.readyState === 3) { // если частично загружено
if(/<\/head>/i.test(xhr.responseText)) { // если в загруженном есть закрывающий тег </head>
resolve(parseHead(xhr.responseText)); // парсим текст и возвращаем head
xhr.onreadystatechange = null; // убираем дальнейшую обработку изменения состояния
xhr.abort(); // останавливаем дальнейшую загрузку
}
} else if (xhr.readyState === 4){ // если запрос завршён
if(xhr.status === 200) // если завершён успешно
resolve(parseHead(xhr.responseText)); // парсим текст и возвращаем head
else
reject(xhr);
}
};
xhr.send();
})
}
getHead('/').then(console.log, console.error)
tab
.form
, и отталкиваясь от позиции элемента фокусировать следующий.dom
, и также не обязательно, что следующим в фокусе должен быть именно следующий по порядку. Для всего этого и придуман tabindex
.