ES6 νκ²½μμ νΈλ€λ°λ₯Ό μ¬μ©ν κ²½μ° λ΄μ₯λ each
ν¬νΌμ μ΄λ μ΄μ μ λ€λ¦ κ°μ²΄λ§ μ§μνλ νκ³κ° μμ΄ λΆνΈν©λλ€. μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ λ°°μ΄, μ§λ, μ§ν©, μ¬μ©μ μ μ λ°λ³΅ κ°λ₯ κ°μ²΄ λ° μΌλ° κ°μ²΄λ₯Ό μ§μνλ μ체 λ²μ μ each
λμ°λ―Έλ₯Ό λ±λ‘νκΈ° μμνμ΅λλ€. κ·Έ λμ°λ―Έλ μλμ μμ΅λλ€.
λ΄μ₯λ each
λμ°λ―Έμμ μ΄λ¬ν μ νμ λͺ©λ‘μ λν μ§μμ λμ
ν κ³νμ΄λ μν₯μ΄ μμ΅λκΉ? λλ νΈλ€λ°κ° ν΄λ¦¬νμ νΌνλ κ²μ λͺ©νλ‘ νλ€λ κ²μ μ΄ν΄νκ³ λΈλΌμ°μ μ§μμ μμμν€μ§ μκ³ μ λμ°λ―Έκ° μλνλλ‘ λ§λλ μ μΌν λ°©λ²μ νκ²½μ κΈ°λ³Έ λλ μ¬μ ν΄λ¦¬ν μ§μμ λ°λΌ λ€μν λͺ©λ‘ μ νμ λν μ§μμ μ μ§μ μΌλ‘ νμ±ννλ κ²μ΄λΌκ³ μμνκΈ° λλ¬Έμ μ§λ¬Έν©λλ€. Set
, Map
λ° Symbol
.
Handlebars.registerHelper("each", function (contexts, options) {
// Throw a runtime exception if options were not supplied.
if (!options) {
throw new Handlebars.Exception("Must pass iterator to #each");
}
// If the "list of contexts" is a function, execute it to get the actual list of contexts.
if (typeof contexts === "function") {
contexts = contexts.call(this);
}
// If data was supplied, frame it.
const data = options.data ? Object.assign({}, options.data, { _parent: options.data }) : undefined;
// Create the string into which the contexts will be handled and returned.
let string = "";
// Create a flag indicating whether or not string building has begun.
let stringExtensionStarted = false;
// Create a variable to hold the context to use during the next string extension. This is done to
// allow iteration through the supplied list of contexts one step out of sync as they are looped
// through later in this helper, ensuring a predictable sequence of value retrieval, string
// extension, value retrieval, string extension...
let nextContext;
// Create a function responsible for expanding the string.
const extendString = (final = false) => {
// If other contexts have been encountered...
if (nextContext) {
// Expand the string using the block function.
string += options.fn(nextContext.value, {
data: data ? Object.assign(data, {
index: nextContext.index,
key: nextContext.key,
first: !stringExtensionStarted,
last: final
}) : undefined,
blockParams: [nextContext.key, nextContext.value]
});
// Note that string extension has begun.
stringExtensionStarted = true;
// If no contexts have been encountered and this is the final extension...
} else if (final) {
// Expand the string using the "else" block function.
string += options.inverse(this);
}
};
// If a list of contexts was supplied...
if (contexts !== null && typeof contexts !== "undefined") {
// Start a counter.
let index = 0;
// If an array list was supplied...
if (Array.isArray(contexts)) {
// For each of the possible indexes in the supplied array...
for (const len = contexts.length; index < len; index++) {
// If the index is in the supplied array...
if (index in contexts) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: index,
value: contexts[index]
};
}
}
// If a map list was supplied...
} else if (contexts instanceof Map) {
// For each entry in the supplied map...
for (const [key, value] of contexts) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: key,
value: value
};
// Increment the counter.
index++;
}
// If an iterable list was supplied (including set lists)...
} else if (typeof contexts[Symbol.iterator] === "function") {
// Get an iterator from the iterable.
const iterator = contexts[Symbol.iterator]();
// Create a variable to hold the iterator's next return.
let next;
// Do the following...
do {
// Iterate and update the variable.
next = iterator.next();
// If there is anything left to iterate...
if (!next.done) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: index,
value: next.value
};
// Increment the counter.
index++;
}
// ... until there is nothing left to iterate.
} while (!next.done);
// If a list other than an array, map, or iterable was supplied...
} else {
// For each key in the supplied object...
for (const key of Object.keys(contexts)) {
// Call the string extension function.
extendString();
// Define the context to use during the next string extension.
nextContext = {
index: index,
key: key,
value: contexts[key]
};
// Increment the counter.
index++;
}
}
}
// Call the string extension a final time now that the last supplied context has been encountered.
extendString(true);
// Return the fully-extended string.
return string;
});
#1557μ μ¬μ©νμ¬ μ§κΈ κ°λ₯ν΄μΌ ν©λλ€.
@nknapp #1557μ ꡬνμ΄ Map
μ λλ‘ μ§μνμ§ μλ κ² κ°μ΅λλ€. νμ¬ [key, value]
Map
μ _entry_ μΈ λ°λ³΅ νλͺ©μ μμ±νλ λ°λ©΄ μμ μμ μ½λλ λ°λ³΅ νλͺ©μ value
λ‘ λ§λ€κ³ @key
, λ΄κ° _μκ°νλ_ λ°λμ§ν κ²μ
λλ€. λμκ² λ°λμ§νλ€!
λν ννμμ νμ¬ Map
λ₯Ό μ§μνμ§ μμΌλ―λ‘ {{person.myMap.myMapKey}}
λΌκ³ λ§ν μ μμ΅λλ€. λλ μ§κΈ μ΄ λ¬Έμ μ λν΄ λ κΉμ΄ νκ³ λ€κ³ μλ€.
runtime.js
$μ lookupProperty
λ₯Ό μΆκ°νλ©΄ Map
μμ μμ±μ μ‘°νν μ μμ΅λλ€.
lookupProperty: function(parent, propertyName) {
if (parent instanceof Map) {
return parent.get(propertyName)
}
μ΄λ° μ§μμ μΆκ°νλ €λ μκ΅¬κ° μμ΅λκΉ?
@karlvr λλ λΉμ μ μ μμ΄ μ‘°μ¬ν κ°μΉκ° μλ€κ³ μκ°ν©λλ€. κ·Έλ¬λ λλ κ·Έκ²μ λν΄ λ Όμνκ³ μΆμ΅λλ€.
@karlvr μ μ§λ μ§μμ λν μλ‘μ΄ λ¬Έμ λ₯Ό μμν μ μμ΅λλ€. μ΄ λ¬Έμ μ μΌλΆλ μ΄λ―Έ ν΄κ²°λμμΌλ©° κΉ¨λν μμμ νκ³ μΆμ΅λλ€.
@nknapp λΉ λ₯Έ λ΅λ³ κ°μ¬ν©λλ€. λ°©κΈ μ μλ λ³κ²½ μ¬νμΌλ‘ PRμ νμ΅λλ€. κ±°κΈ°μμ λ Όμν μ μμκΉμ? #1679
κ°μ₯ μ μ©ν λκΈ
@karlvr μ μ§λ μ§μμ λν μλ‘μ΄ λ¬Έμ λ₯Ό μμν μ μμ΅λλ€. μ΄ λ¬Έμ μ μΌλΆλ μ΄λ―Έ ν΄κ²°λμμΌλ©° κΉ¨λν μμμ νκ³ μΆμ΅λλ€.