Javascript
__proto__
Если свойство не находится в объекте (например obj.property
), то оно ищется в obj.__proto__.property
. Затем в obj.__proto__.__proto__.property
и так до тех пор, пока следующий __proto__
не окажется равным null
.
prototype.constructor
Все функции имеют свойство prototype
, у которого по умолчанию имеется единственное свойство constructor
, в котором хранится сама функция.
new()
Когда исполняется new Foo(...)
, происходит следующее:
- Создается новый объект, наследующий Foo.prototype. То есть, примерно так:
var newFoo = { __proto__: Foo.prototype}
- Вызывается конструктор — функция Foo с указанными аргументами и this, привязанным к только что созданному объекту. new Foo эквивалентно new Foo(), то есть если аргументы не указаны, Foo вызывается без аргументов.
- Результатом выражения new становится объект, возвращенный конструктором. Если конструктор не возвращает объект явно, или возвращает примитивный тип, то используется объект из п. 1.
Альтернативное объяснение:
new Test():
- create
new Object()
obj - set
obj.__proto__
toTest.prototype
return Test.call(obj) || obj;
// normally obj is returned but constructors in JS can return a value
Примеры
var Math = function() { };
Math.prototype.add = function(a,b) { return a + b; };
var m = new Math(); // Math.prototype
m.add(5,6); // 11
var Math = function() { return { msg: "hello" } };
Math.prototype.add = function(a,b) { return a + b; };
var m = new Math(); // { msg: "hello" }
m.add; // undefined
Object.create()
Object.create(prototype, descriptors)
Создает объект "из воздуха", используя переданный первым аргументом объект в качестве __proto__
. Если в качестве прототипа передать null
, то полученный объект не будет иметь прототипа. Дескриптор содержит атрибуты value
, writable
, enumerable
, configurable
.
var newObj = Object.create(null, {
size: {
value: "large",
enumerable: true
},
shape: {
value: "round",
enumerable: true
}
});
Отличие от new
Можно сказать, что new X
это тоже самое, что Object.create(X.prototype)
, только еще будет запущен конструктор X.
for...in
Цикл for-in для массива/объекта итерирует не по элементам, а по их индексам/ключам:
var arr = [9, 2, 5];
for(var item in arr) {
console.log(item); // 1, 2, 3
}
В ES6 есть цикл for...of
, итерирующий по значениям:
var arr = [9, 2, 5];
for(var item of arr) {
console.log(item); // 9, 2, 5
}
Вопрос про замыкания
var funcs = [];
// create a bunch of functions
for (var i = 0; i < 3; i++) {
funcs.push(function() {
console.log(i);
})
}
// call them
for (var j = 0; j < 3; j++) {
funcs[j]();
}
Этот код выдаст 3, 3, 3
. Объявить локальную переменную в теле цикла не поможет, так как в JS функции имеют function-scope область видимости.
Приходится использовать IIFE:
var funcs = [];
// create a bunch of functions
for (var i = 0; i < 3; i++) {
(function() {
var local = i;
funcs.push(function() {
console.log(local);
})
})();
}
// call them
for (var j = 0; j < 3; j++) {
funcs[j]();
}
В ES6 проблема решается простой заменой var
на let
в первом цикле:
var funcs = [];
// create a bunch of functions
for (let i = 0; i < 3; i++) { // Note the use of let
funcs.push(function() {
console.log(i);
})
}
// call them
for (var j = 0; j < 3; j++) {
funcs[j]();
}