JavaScript와 레거시 ExtendScript 표현식 엔진 간 구문 차이

이 문서에서는 JavaScript와 After Effects 16.0의 레거시 ExtendScript 표현식 엔진 간 표현식 언어 구문 차이에 대해 설명합니다.

JavaScript 표현식 엔진에 맞게 표현식을 개선하는 방법 또는 이전 After Effects 릴리스용으로 작성된 표현식이 JavaScript 표현식 엔진에서 평가되지 않을 때 발생하는 오류를 수정하는 방법에 대해 자세히 알아보려면 다음 문서를 참조하십시오.

After Effects의 표현식 언어는 ECMAScript의 구현인 JavaScript를 기반으로 합니다. After Effects 16.0의 JavaScript 표현식 엔진은 ECMAScript 2018을 기반으로 합니다. 레거시 ExtendScript 표현식 엔진은 ECMAScript 3(1999)를 기반으로 합니다. (Adobe ExtendScript는 After Effects 및 기타 Adobe 애플리케이션에서 스크립팅에 사용되는 언어이기도 합니다.)

아래 제공된 예를 그대로 사용하거나 JavaScript 및 레거시 ExtendScript 표현식 엔진 모두에서 작동하는 표현식을 작성하기 위한 지침으로 사용할 수 있습니다.

JavaScript와 레거시 ExtendScript 표현식 엔진 간의 주요 차이는 다음과 같습니다.

최신 JavaScript 구문: 표현식 언어가 개선됨

표현식에 ECMAScript 2018의 JavaScript 구문 사용 가능

ECMAScript 3 이후 JavaScript 언어에 많은 기능이 추가되었습니다. 문자열, 배열 및 개체에 사용 가능한 더 간결하고 쉽게 읽을 수 있는 메서드가 새로 추가되었습니다. 또한 변수와 함수, 기본 매개 변수, 스프레드 연산자 등을 선언하는 새로운 방법이 추가되었습니다. 이러한 변경 내용은 JavaScript 언어에 일반적인 사항이므로 이 문서에서 다루지 않습니다. 추가된 많은 구문에 대한 자세한 내용은 다음 링크에서 제공하는 리소스를 참조하십시오.

JavaScript에 대해 자세히 알아볼 수 있는 추가 권장 리소스:

소스 텍스트의 다른 속성에 연결할 때 더 이상 .value가 필요하지 않음

소스 텍스트 속성에서 다른 속성 값을 참조할 때 레거시 ExtendScript 엔진에서는 속성의 끝에 .value가 추가되어야 합니다. JavaScript 엔진은 .propertyIndex 또는 .name과 같은 다른 특성이 명시적으로 사용되지 않으면 기본적으로 속성의 값을 표시합니다.

예를 들면 다음과 같습니다.

thisComp.layer("Solid 1").transform.position
 
// In the Legacy engine, this evaluates to "[object Property]" when applied to a Source Text property.
// In the JavaScript engine, this evaluates to the value of the Position property of layer "Solid 1" when applied to a Source Text property.

posterizeTime(0)을 사용하여 속성 값 고정

After Effects 16.0에서는 posterizeTime(0)이 컴포지션의 시간 0에 속성 값을 고정합니다. 이 사항은 JavaScript와 레거시 ExtendScript 엔진 모두에 적용됩니다.

참고:

이전 버전과 호환되지 않으므로 16.0 이전의 After Effects 버전에서는 예기치 않은 결과를 야기할 수 있습니다.

호환되지 않는 레거시 구문

레거시 ExtendScript 표현식 엔진의 거의 모든 표현식 구문은 JavaScript 표현식 엔진과 호환됩니다. 그러나 JavaScript 표현식 엔진과 호환되지 않는 일부 레거시 구문이 있습니다. 이는 최신 JavaScript의 구문 변경으로 인해 야기될 수 있습니다. 사용되지 않거나 오래된 구문이 제거되었기 때문일 수도 있습니다. 아래에는 작동하지 않는 구문과 작동하는 구문의 예가 나와 있습니다.

대부분의 구문 차이는 표현식을 다시 작성하는 애플리케이션 스크립팅을 통해 수정할 수 있습니다.

if...else 구문 차이

일반적으로 if...else 문은 MDN 지침에 따라 항상 줄 바꿈과 대괄호를 사용하여 작성하는 것이 좋습니다. 레거시 ExtendScript 엔진은 if...else 문의 느슨한 구문에 관대하지만 JavaScript 엔진은 엄격합니다. JavaScript 엔진을 사용할 때는 if...else 문이 평가되지 않습니다.

else 없는 if 문으로 표현식을 끝내는 것이 허용되지 않음

표현식이 else 문이 없는 if 문으로 끝날 경우 JavaScript 엔진이 표현식을 평가하지 못하고 "정의되지 않은 값이 표현식에 사용되었습니다(범위를 벗어나는 배열 하위 스크립트일 수 있습니까?)"와 같은 오류가 표시됩니다. 레거시 ExtendScript 엔진에서는 시간이 1초보다 크면 다음 표현식이 100으로 평가되고 그렇지 않으면 50으로 평가됩니다.

var x = 50;
if ( time > 1 ) {
    x = 100
}
// The "else" here is implied but not stated.

JavaScript 엔진을 사용할 때는 문의 else 부분이 표현식의 마지막 문일 경우 명시적으로 표현되어야 합니다.

var x = 50;
if ( time > 1 ) {
    x = 100;
} else {
    x;
}

이 경우 JavaScript 엔진과 레거시 ExtendScript 엔진 모두에서 표현식이 올바르게 평가됩니다.

if와 else가 대괄호 없이 같은 줄에 나올 수 없음

if...else 문이 대괄호 없이 같은 줄에 나올 경우 레거시 ExtendScript 엔진에서는 문이 평가되지만 JavaScript 엔진에서는 문이 평가되지 않고 "구문 오류: 예기치 않은 토큰 " 또는 "정의되지 않은 값이 표현식에 사용되었습니다(범위를 벗어나는 배열 하위 스크립트일 수 있습니까?)"와 같은 오류가 표시됩니다. 표시되는 오류는 컨텍스트 및 속성 유형에 따라 달라질 수 있습니다.

레거시 ExtendScript 엔진에서는 시간이 1초보다 크면 다음 표현식이 100으로 평가되고 그렇지 않으면 50으로 평가됩니다.

if ( time > 1 ) 100 else 50;

JavaScript 엔진에서는 if...else 문이 평가되려면 줄 바꿈이나 대괄호를 사용해야 합니다. 단순한 예로, 삼항 연산자를 대신 사용할 수 있습니다. 다음은 JavaScript 엔진에 사용할 수 있는 구문입니다.

// Solution A: adding a line break before "else" will allow both engines to evaluate correctly.
 
if ( time > 1 ) 100
else 50;
 
// Solution B: adding correct bracketing will also allow both engines to evaluate correctly.
 
if ( time > 1 ) { 100 } else { 50 };
 
// Solution C: Use a ternary operator in place of the if...else statement, which also evaluates correctly in both engines.
 
time > 1 ? 100 : 50;

위의 해결 방법을 사용하면 JavaScript 엔진과 레거시 ExtendScript 엔진 모두에서 표현식이 올바르게 평가됩니다.

표현식이 함수 선언으로 끝날 수 없음

표현식이 함수 선언으로 끝나면 JavaScript 엔진이 표현식을 평가하지 못하고 "숫자, 배열 또는 속성이 필요한 개체 유형이 있습니다."와 같은 오류가 표시됩니다. JavaScript 엔진에서는 평가된 마지막 항목이 값을 선언하는 대신 반환해야 합니다.

다음 예는 레거시 엔진에서는 작동하지만 JavaScript 엔진에서는 작동하지 않습니다.

timesTen( value );  // The Legacy engine evaluates this line, even though the function is declared below.
 
function timesTen ( val ) {
    return val * 10
}

함수가 마지막 줄로 선언되는 대신 호출될 경우에는 두 엔진 모두에서 표현식이 올바르게 평가됩니다.

function timesTen ( val ) {
    return val * 10
}
 
timesTen( value );  // The JavaScript engine needs the function call to happen below the declaration in order to return the correct value.

this() 약식 구문이 허용되지 않음( 대신 thisLayer() 사용)

레거시 ExtendScript 엔진에서는 thisLayer에 대한 약식 구문으로 this의 사용이 허용되었습니다.JavaScript 엔진에서는 this가 전체 개체를 참조하므로 대신 thisLayer를 사용해야 합니다. JavaScript 엔진에서 this를 사용하면 일반적으로 "함수가 아닙니다."와 같은 오류가 표시됩니다.

다음 레거시 ExtendScript 예에서는 this가 소스 텍스트 속성의 텍스트 레이어 위치 속성에 대한 압축 링크를 만드는 데 사용됩니다.

this(5)(2).value;

JavaScript 엔진에서는 this를 thisLayer로 대체해야 합니다.

thisLayer(5)(2).value;

thisLayer 사용은 두 표현식 엔진 모두에서 호환됩니다.

문자에 대한 소스 텍스트 속성 배열-색인 액세스에 .value 필요

레거시 ExtendScript 표현식 엔진에서는 배열처럼 대괄호 표기를 사용하여 텍스트 속성의 문자에 액세스할 수 있었습니다.

text.sourceText[0]      // Returns the first character of the Source Text property's text value.

JavaScript 엔진에서는 문자에 액세스하려면 .value를 추가해야 합니다.

text.sourceText.value[0]    // Returns the first character of the Source Text property's text value.

이 구문은 두 엔진 모두와 호환됩니다.

속성 및 메서드 스네이크 케이스(snake case)가 허용되지 않음

사용되지 않는 스네이크 케이스(snake case) 속성 및 메서드(카멜 케이스 대신 밑줄을 사용하여 작성됨)는 JavaScript 엔진에서 지원하지 않습니다. 두 엔진 모두와 호환되는 카멜 케이스 버전을 사용해야 합니다. 다음은 사용되지 않는 스네이크 케이스(snake case) 및 해당하는 카멜 케이스의 목록입니다.

스네이크 케이스(snake case) 속성

카멜 케이스 속성

스네이크 케이스(snake case) 메서드

카멜 케이스 메서드

this_comp

this_layer

this_property

color_depth

has_parent

in_point

out_point

start_time

has_video

has_audio

audio_active

anchor_point

audio_levels

time_remap

casts_shadows

light_transmission

accepts_shadows

accepts_lights

frame_duration

shutter_angle

shutter_phase

num_layers

pixel_aspect

point_of_interest

depth_of_field

focus_distance

blur_level

cone_angle

cone_feather

shadow_darkness

shadow_diffusion

active_camera

thisComp

thisLayer

thisProperty

colorDepth

hasParent

inPoint

outPoint

startTime

hasVideo

hasAudio

audioActive

anchorPoint

audioLevels

timeRemap

castsShadows

lightTransmission

acceptsShadows

acceptsLights

frameDuration

shutterAngle

shutterPhase

numLayers

pixelAspect

pointOfInterest

depthOfField

focusDistance

blurLevel

coneAngle

coneFeather

shadowDarkness

shadowDiffusion

activeCamera

value_at_time()

velocity_at_time()

speed_at_time()

nearest_key()

posterize_time()

look_at()

seed_random()

gauss_random()

ease_in()

ease_out()

rgb_to_hsl()

hsl_to_rgb()

degrees_to_radians()

radians_to_degrees()

from_comp_to_surface()

to_comp_vec()

from_comp_vec()

to_world_vec()

from_world_vec()

to_comp()

from_comp()

to_world()

from_world()

temporal_wiggle()

loop_in_duration()

loop_out_duration()

loop_in()

loop_out()

valueAtTime()

velocityAtTime()

speedAtTime()

nearestKey()

posterizeTime()

lookAt()

seedRandom()

gaussRandom()

easeIn()

easeOut()

rgbToHsl()

hslToRgb()

degreesToRadians()

radiansToDegrees()

fromCompToSurface()

toCompVec()

fromCompVec()

toWorldVec()

fromWorldVec()

toComp()

fromComp()

toWorld()

fromWorld()

temporalWiggle()

loopInDuration()

loopOutDuration()

loopIn()

loopOut()

이진 인코딩(.jsxbin) 표현식에 eval() 사용

ExtendScript 이진 형식으로 인코딩된 표현식(ExtendScript ToolKit CC에서 이진 .jsxbin 파일로 저장됨)은 JavaScript 엔진에서 지원하지 않습니다.

표현식을 난독화하려면 레거시 ExtendScript 엔진을 사용하거나 ECMAScript 2018과 호환되는 다른 난독화 메서드를 사용하십시오. 몇몇 난독화 메서드는 두 표현식 엔진 중 하나와 호환되지 않을 수 있습니다.

$.(달러) 개체에 대한 지원 제한

$.(달러) 개체의 메서드와 속성은 ExtendScript에 고유하며 JavaScript 엔진에서는 대부분 지원되지 않습니다. 다음 표에는 $.(달러) 개체의 지원되지 않는 용례 및 지원되는 용례가 나와 있습니다.

지원되지 않는 $.

지원되는 $.

$.fileName

$.hiResTimes

$.stack

$.evalFile()

$.list()

$.setenv()

$.getenv()

$.appEncoding

$.buildDate

$.decimalPoint

$.dictionary

$.error

$.flags

$.includePath

$.level

$.line

$.locale

$.localize

$.memCache

$.os

$.screens

$.strict

$.version

$.build

$.engineName(레거시 ExtendScript 엔진에서는 지원되지 않음)

$.global

...reflect.properties, ...reflect.methods 및 toSource()가 지원되지 않음

reflect.properties 및 reflect.methods는 JavaScript 엔진에서 지원되지 않습니다. ExtendScript에 고유한 메서드이며 JavaScript에는 직접적으로 해당하는 메서드가 없습니다.

toSource() JavaScript에서는 사용도지 않으며 표준 트랙의 일부가 아닙니다.

특정 After Effects 속성에 대해 위 메서드가 제공한 것과 유사한 사용 가능한 속성 및 메서드의 목록을 보려면 소스 텍스트 속성에 다음 표현식을 사용하고 원하는 속성에 연결하십시오. 예를 들어, 줄 1에서 thisProperty 대신 pick whip을 사용합니다.

let obj = thisProperty;     // Replace "thisProperty" with a property-link to your desired property.
let props = [];
 
do {
    Object.getOwnPropertyNames(obj).forEach(prop => {
        if (props.indexOf(prop) === -1) {
            props.push(prop);
        }
    });
} while (obj = Object.getPrototypeOf(obj));
 
props.join("\n");           // Returns an array of strings listing the properties and methods available.

위의 표현식은 레거시 ExtendScript 엔진과 호환되지 않습니다. 위 표현식에는 ECMAScript 3에서 사용할 수 없는 구문과 메서드가 사용되었습니다.

JavaScript 엔진을 사용한 .jsx 표현식 라이브러리 및 eval()에 대한 구문 요구 사항

.jsx 표현식 함수 라이브러리 내에서 표현식을 사용할 경우 또는 eval() 내에서 표현식이 호출될 경우 특정 구문을 수정해야 합니다.

명시적 thisLayer. 또는 thisProperty.레이어 또는 속성에 대해 명시적으로 호출되지 않는 기본 메서드 또는 특성에 접두사가 추가되어야 합니다. 접두사는 메서드 또는 특성을 호출하는 대상 개체가 무엇인지를 JavaScript 엔진에 알립니다.

Position과 같은 배열 값에 대한 수학 연산의 경우, 배열의 모든 항목에서 수학 연산이 작동하려면 벡터 함수나 루프 함수를 사용하여 계산되어야 합니다. position + [100,100]과 같은 오버로드된 수학 연산자는 평가되지 않습니다.

JavaScript 엔진을 사용할 경우, 일부 레거시 ExtendScript 표현식 구문을 새로운 엔진이 읽을 수 있으려면 평가 전에 표현식이 사전 처리되어야 합니다. 그러나 .jsx 표현식 함수 라이브러리의 표현식을 평가할 때나 표현식이 eval() 내에서 호출될 때는 이러한 사전 처리 작업이 수행되지 않습니다. 이러한 경우 위의 구문 수정이 수동으로 이루어져야 합니다. 이러한 모든 구문 수정은 레거시 ExtendScript 엔진과 호환되므로 JavaScript 엔진에서 작동하도록 작성된 .jsx 표현식 라이브러리는 레거시 ExtendScript 엔진에서도 작동합니다.

성능 팁: 사전 처리가 수행되지 않으므로 이 구문 및 JavaScript 엔진을 사용하여 .jsx 라이브러리에서 복잡한 표현식을 호출할 경우 동일한 표현식을 속성에 대해 직접 호출할 때와 비교해 성능이 향상될 수 있습니다.

기본 메서드 및 특성에 명시적으로 thisLayer. 또는 thisProperty. 접두사 지정

다음 표에는 접두사가 필요한 메서드 및 특성이 나와 있습니다. 예를 들어, 시간은 thisLayer.time으로 작성하고 wiggle()thisProperty.wiggle()로 작성해야 합니다. 

이러한 접두사는 특성이나 메서드가 이미 다른 레이어 또는 속성에 대해 명시적으로 호출되지 않은 경우에만 필요합니다. 예를 들어, thisComp.layer(1).hasParent를 호출할 때 thisLayer.를 추가하지 않아도 됩니다. 이미 .hasParentlayer(1)에서 명시적으로 호출되었기 때문입니다.

thisLayer.가 필요한 메서드

thisLayer.가 필요한 특성

thisProperty.가 필요한 메서드

thisProperty.가 필요한 특성

comp()
footage()
posterizeTime()
add()
sub()
mul()
div()
clamp()
length()
dot()
normalize()
cross()
lookAt()
timeToFrames()
framesToTime()
timeToTimecode()
timeToFeetAndFrames()
timeToNTSCTimecode()
timeToCurrentFormat()
seedRandom()
random()
gaussRandom()
noise()
degreesToRadians()
radiansToDegrees()
linear()
ease()
easeIn()
easeOut()
rgbToHsl()
hslToRgb()
hexToRgb()
mask()
sourceRectAtTime()
sourceTime()
sampleImage()
toComp()
fromComp()
toWorld()
fromWorld()
toCompVec()
fromCompVec()
toWorldVec()
fromWorldVec()
fromCompToSurface()

time
source
thisProject
colorDepth
transform
anchorPoint
position
scale
rotation
opacity
orientation
rotationX
rotationY
rotationZ
lightTransmission
castsShadows
acceptsShadows
acceptsLights
ambient
diffuse
specular
specularIntensity
shininess
specularShininess
metal
audioLevels
timeRemap
marker
name
width
height
index
parent
hasParent
inPoint
outPoint
startTime
hasVideo
hasAudio
active
enabled
audioActive
cameraOption
pointOfInterest
zoom
depthOfField
focusDistance
aperature
blurLevel
irisShape
irisRotation
irisRoundness
irisAspectRatio
irisDiffractionFringe
highlightGain
highlightThreshold
highlightSaturation
lightOption
intensity
color
coneAngle
coneFeather
shadowDarkness
shadowDiffusion

valueAtTime()
velocityAtTime()
speedAtTime()
wiggle()
temporalWiggle()
smooth()
loopIn()
loopOut()
loopInDuration()
loopOutDuration()
key()
nearestKey()
propertyGroup()
points()
inTangents()
outTangents()
isClosed()
pointsOnPath()
tangentOnPath()
normalOnPath()
createPath()

velocity
speed
numKeys
propertyIndex

수학 연산자를 벡터 수학 함수로 대체

JavaScript와 LegacyExtendScript 엔진 모두 배열에 대해 position + [100,100]과 같은 구문을 사용하여 수학 연산자를 오버로드하는 것을 허용하지만 .jsx 표현식 함수 라이브러리 내의 식이나 eval() 내의 식에 대해서는 작동하지 않습니다.

Position, Scale 등과 같은 배열 속성에 대해 수학 연산을 수행하려면 더하기, 빼기, 곱하기 및 나누기를 위해 각각에 해당하는 벡터 수학 함수를 사용해야 합니다. 벡터 수학 함수는 일반 숫자에 대해서도 작동하므로 두 데이터 유형 중 하나의 속성에 대해 호출될 수 있는 함수는 벡터 수학 함수를 사용해야 합니다.

참고:

thisLayer. 접두사는 벡터 수학 함수와 함께 사용해야 합니다.

  • 더하기: thisLayer.add(vec1, vec2)
  • 빼기: thisLayer.sub(vec1, vec2)
  • 곱하기: thisLayer.mul(vec, amount)
  • 나누기: thisLayer.div(vec, amount)

다음은 표준 수학 함수와 업데이트된 벡터 함수를 사용한 표현식의 예입니다. 또한 벡터 수학 함수는 필요한 경우 적절한 thisLayer.또는 thisProperty. 접두사를 사용합니다.

Position 속성의 wiggle()과 값 간의 차이를 찾으려면:

// Standard Math:
wiggle() - value;
 
 
// Vector Math:
thisLayer.sub( thisProperty.wiggle(), value );

linear()와 유사하지만 확장 범위가 정의된 최소 및 최대를 넘도록 두 값 간을 보간하려면:

// Standard Math:
value1 + ( ( t - tMin ) / ( tMax - tMin ) ) * ( value2 - value1 );
 
 
// Vector Math:
thisLayer.add( value1, thisLayer.mul( thisLayer.div( thisLayer.sub( t, tMin ), thisLayer.sub( tMax, tMin ) ), thisLayer.sub( value2, value1 ) ) );

Position 속성을 안과 밖으로 루프하려면:

// Standard Math:
loopIn( "cycle" ) + loopOut( "cycle" ) - value;
 
 
// Vector Math:
thisLayer.sub( thisLayer.add( thisProperty.loopIn( "cycle" ), thisProperty.loopOut( "cycle" ) ), value );

유사 검색

Adobe 로고

내 계정 로그인