귀하의 질문은 자바 스크립트 렌즈를 사용하는 방법에 대해입니다 : 여기에 내 게시물의 코드 단편이다? 그렇다면 도움을 드릴 수 있습니다. Ramda.js library을 확인 했습니까? 그것은 기능적인 JS를 작성하는 훌륭한 방법입니다. 의는 적 모델을보고 시작하자 :
/* -- data model -- */
let enemyModel = {
name: "badguy1",
stats: {
health: 10,
strength: 42
},
pos: {
x: 100,
y: 101
}
};
렌즈 : 당신이 게터 방법 및 특정 개체에 대한 setter 메소드를 필요로 렌즈를 구성하기 위해를 -은 "적"귀하의 경우. 다음은 직접 작성하는 방법입니다.
방법 1 : 오브젝트
당신이 렌즈를 만든 후에 const healthLens = lensPath(['stats', 'health']);
에 대한 Ramda의 편법 편리 렌즈는, 그것의 : 자신의 getter 및 setter
const getHealth = path(['stats', 'health']);
const setHealth = assocPath(['stats', 'health']);
const healthLens = lens(getHealth, setHealth);
방법 2를 만들기 그것을 사용할 시간. Ramda는 렌즈 사용을위한 3 가지 기능, 즉 view(..)
, set(..)
및 over(..)
을 제공합니다.
view(healthLens)(enemyModel); // 10
set(healthLens, 15)(enemyModel); // changes health from 10 to 15
over(healthLens, fireDamage)(enemyModel); // reduces enemyModel's health property by 10
당신은 적의 건강에 fireDamage(..)
함수를 적용하고 있기 때문에, 당신은 over(..)
를 사용하는 것이 좋습니다. 또한 위치 좌표가 enemyModel 내에 중첩되어 있기 때문에 렌즈를 사용하여 해당 좌표에 액세스하려고 할 것입니다. 우리가 그것에있는 동안 하나와 리펙터를 만들어 봅시다. isInRange(..)
.
/* -- lenses -- */
const xLens = lensPath(['pos', 'x']);
const yLens = lensPath(['pos', 'y']);
const ptLens = lens(prop('pos'), assoc('pos'));
// since idk where 'radius' is coming from I'll hard-code it
let radius = 12;
const filterInRange = rad => filter(
over(ptLens, isInRange(rad)) // using 'ptLens' bc isInRange(..) takes 'radius' and a 'point'
);
const mapFireDamage = map(
over(healthLens, fireDamage) // using 'healthLens' bc fireDamage(..) takes 'health'
);
let newEnemies = compose(
mapFireDamage,
filterInRange(radius)
)(enemies);
: 여기 /* -- helper functions -- */
const square = x => x * x;
const gteRadSquared = radius => flip(gte)(square(radius));
let sumPointSquared = point => converge(
add,
[compose(square, prop('x')),
compose(square, prop('y'))]
)(point);
sumPointSquared = curry(sumPointSquared); // allows for "partial application" of fn arguments
/* -- refactored fn -- */
let isInRange = (radius, point) => compose(
gteRadSquared(radius),
sumPointSquared
)(point);
isInRange = curry(isInRange);
가 그 enemyModels의 모음을 처리 할 때 같이 할 작업은 다음과 같습니다
이 // NOTE: not sure if this works as you intended it to...
function isInRange(radius, point) {
return point.x^2 + point.y^2 >= radius^2; // maybe try Math.pow(..)
}
여기에 기능적 접근 방식 : 참고로
, 여기에 원점 FN의 렌즈가 얼마나 유용 할 수 있는지 알려주는 데 도움이되기를 바랍니다.많은 헬퍼 함수가 있지만, 코드의 마지막 부분은 슈퍼 의미론이라고 생각합니다!
마지막으로 RamDA의 이러한 기능을 사용하여이 범위를 범람시켜이 예제를 더 읽기 쉽게 만들어 보겠습니다. 나는 이것을 달성하기 위해 ES6 해체를 사용하고있다. 방법은 다음과 같습니다.
const {
add,
assocPath,
compose,
converge,
curry,
filter,
flip,
gte,
lens,
lensPath,
map,
over,
set,
path,
prop,
view
} = R;
// code goes below...
jsBin에서 사용해보세요! Ramda를 지원합니다.
@DustinGetz 그렇다면 Javascript로 변환 하시겠습니까? –
@DustinGetz '렌즈 라이브러리 (lens libraries)'의 스타일 (즉, 함수의 함수)로 정확하게하려고합니까? 아니면 일류 게터와 세터를 만들고 있습니까? –
내 값은 더 깊숙이 중첩되어 있지만 그래프가 아닙니다. 깊이 4라고 말하십시오. 기능의 기능이 필요하다고 생각합니다. –