์ ํํ ๋ง๊ณ ๋ง์ ๋ฒ์ ์ค ES6 ์ผ๊น?
๐ ๊ณต๋ถ ๋ฐฐ๊ฒฝ
์๋ฐ์คํฌ๋ฆฝํธ์์ ์ธ๋ถ ๋ชจ๋์ ๊ฐ์ ธ์ค๋ ๋ฐฉ์์ธ import์ require์ ๊น์ด ํ๊ณ ๋ค๋ค๊ฐ, import ๋ฌธ์ ์ฌ์ฉํ๋ ES6, require ๋ฌธ์ ์ฌ์ฉํ๋ CommonJS๊น์ง ๊ณต๋ถํ๊ฒ ๋์๋ค.
์ด ๋ฌธ์์์๋ ๋ง๊ณ ๋ง์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ ์ค ์ ํํ ES6๊ฐ ํ์์ ์ผ๋ก ์ธ๊ธ๋๊ณ , ๋ํ์ ์ผ๋ก ์ด๊ฐ ์ด๋ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ๋์ง์ ๋ํ์ฌ ์ ๋ฆฌํ์๋ค.
๊ทธ ๊ณผ์ ์์ ๋จ์ํ ํธ์๋ฅผ ์ํด ์ฌ์ฉํ๋ ํ์ดํ ํจ์, ๋ด๊ฒ๋ ๋ชจํธํ๋ ํด๋์ค ๋ฌธ๋ฒ๊ณผ-ํ๋กํ ํ์ ์ ๊ด๊ณ์ฑ์ ๋ํด ์ถ๊ฐ ๊ณต๋ถ๋ฅผ ํ ์ ์์๋ค.
๐ ES6? ECMAScript? Netscape? ๋์ฒด ๋ญ์ผ
์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ๋ฐํ Netscape๊ฐ, ๊ท๊ฒฉํ๋ ํ์ค์ ์น์ธํ๋ ๊ณต์ ๊ธฐ๊ด Ecma์ ์ ์ถํ ํ์ค์ด ECMA-262์ด๋ค. ๊ทธ ํ์คํ๋ ๊ท๊ฒฉ์ ๋ฐ๋ฅด๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ์๋ก์ด ์ด๋ฆ์ด ๋ฐ๋ก ECMAScript.
ES6 ํ์ค์ ๋ฐ๋ฅธ๋ค๋ ์๋ฏธ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ ECMA ๊ท๊ฒฉ์ ๋ฐ๋ฅธ๋ค๋ ์๋ฏธ์ด๋ค.
๐ ES6, ES6.. ํํ ์?
(2023 1์ ๊ธฐ์ค) ํ์ฌ๊น์ง ES13๊น์ง ๋ฐฐํฌ๊ฐ ๋์๋๋ฐ ES6 ES6์ ๋ค๋ค ์ง์ฐฉํ๋ ์ด์ ๋ ๋ฌด์์ผ๊น?
- ๊ธฐ์กด์ ๋ฌธ์ ๋ค์ ๋งค์ฐ ๊น๋ํ๊ฒ ํด๊ฒฐ
- ๊ฐ๋ ์ฑ, ์ ์ง ๋ณด์์ฑ์ ๋ณด๊ฐํ๋ ๋ฌธ๋ฒ์ด ๋๊ฑฐ ์ถ๊ฐ
- โ ๊ทธ์ ๋ฐ๋ผ ์ ๋ช ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๊ฐ๋ฐ ํ๊ฒฝ๋ ES6๋ก ๋ฐ๋!
- IE์์๋ ์ง์ํ์ง ์์ง๋ง Babel์ ์ด์ฉํ๋ฉด ํธํ์ฑ ๋ฌธ์ ๋ ์์
์ด๋ฌํ ๋ฒ ๋ํ์ผ๋ก ES6์ ํนํ! ์ง์ฐฉํ๊ฒ ๋์๋ค.
๐ ๊ธฐ์กด ๋ณ์ ์ ์ธ ๋ฐฉ์์ ๋ฌธ์ ?
๋ฌธ์ 1. var ๋ณ์๋ ์ธ์ ๋ ๋ณ๊ฒฝ ๊ฐ๋ฅํ์ฌ ์ด์ ์ ๋ช ๋ช ๊ท์น์ ๋๋ฌธ์ || _์ธ๋์ค์ฝ์ด๋ก๋ง ์ ํํ์์
๋ฌธ์ 2. var ๋ณ์๋ ๊ฐ์ ๋ณ์ ์ฌ์ ์ธ์ ํ์ฉํ์ฌ ๊ฐ์ด ๋ณ๊ฒฝ๋์์ ๋ ์ด๋์ ๋ณ๊ฒฝ๋์๋์ง ์ถ์ ์ด ์ด๋ ค์์ง.
๋ฌธ์ 3. var ๋ณ์๋ ํจ์ ๋จ์์ ์ค์ฝํ๋ฅผ ๊ฐ์ง. ๋ธ๋ก ์ธ๋ถ์์ if/for ๋ฌธ ๋ธ๋ก ์ธ๋ถ์์๋ var ๋ณ์ ๋ณ์ ์ ๊ทผ ๊ฐ๋ฅ
function welcome(name){
if (!name){
var errMsg = "no name error!"
}
console.log(name);
console.log(errMsg); // "no name error!". ํจ์ ๋จ์์ ์ค์ฝํ๋ฅผ ๊ฐ์ ธ if ๋ธ๋ก ์ธ๋ถ์์์์๋ ๋ณ์ ์ ๊ทผ ๊ฐ๋ฅ
}
welcome();
๋ฌธ์ 4. ๋ณ์ ์ ์ธ ์ ์ ๋ณ์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ ํธ์ด์คํ * ๋ฐ์
(*ํธ์ด์คํ ? ํธ์ด์คํ ? ๋ณ์, ํจ์ ๋ฑ ์ ์ธ๋ฌธ์ ์ต์๋จ์ ์ค์ฝํ๋ก ๋์ด์ฌ๋ ค ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋จผ์ ํ ๋นํ๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ด๋ถ ํ์. ๋๋ฌธ์ var๋ก ์ ์ธ๋ ๋ชจ๋ ๋ณ์๋ ์ค์ฝํ ์ ๋์์ ์ ์ธ๊ณผ ์ด๊ธฐํ ๋จ๊ณ๊ฐ ํ ๋ฒ์ ์ด๋ฃจ์ด์ ธ์ ๋ณ์ ์ ์ธ๋ฌธ ์ด์ ์ ๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ๋จ. )
console.log(foo); // undefined
var foo;
console.log(bar); // Error: Uncaught ReferenceError: bar is not defined
let bar;
๐ ์ด๋ป๊ฒ ํด๊ฒฐํ์๊น?
์๋ก์ด ๋ณ์ ์ ์ธ ๋ฐฉ์์ด ๋ฑ์ฅํ๊ฒ๋๋ค. let, const
let์ผ๋ก ์ ์ธ๋ ๋ณ์๋ ๋ณ์์ ์ ์ธ๊น์ง ์ผ์์ ์ฌ๊ฐ์ง๋ (Temporary Dead Zone)์ด๋ผ๋ ๋ฐ๋ก ๋น ์ ธ์ ๋ณ์๊ฐ ์ ์ธ๋ฌธ ์ด์ ์ ๋ณ์๋ฅผ ์ฐธ์กฐํ ์ ์๊ฒ ๋จ. ๋ํ let, const๋ ๋ธ๋ก ์ค์ฝํ๋ฅผ ๊ฐ์ง๊ธฐ์ ์ธ๋ถ ๋ธ๋ก์์ ์ ๊ทผ์ด ๋ถ๊ฐํจ.
function welcome(name){
if (!name){
let errMsg = "no name error!" // ๋ธ๋ก ์ธ๋ถ์์ ์ ๊ทผ ๋ถ๊ฐ
}
console.log(name);
console.log(errMsg); // Err: errMsg is not defined
}
welcome();
๐ ํ์ค ์์ฝ
๋ณ์์ ์ ์ธ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก const ์ฌ์ฉ, ์ฌํ ๋น์ด ํ์ํ ๊ฒฝ์ฐ์๋ let์ ์ฌ์ฉํ์.
(ํ์ง๋ง ํ๋ก์ ํธ๋ฅผ ํ๋ฉด์ var๋ฅผ ์จ๋ ๋ฌด๊ดํ ๊ฒฝ์ฐ๋ ์์๋ค ๋ค์ ํฌ์คํ ์์ ๋ค๋ค๋ณด๊ฒ ๋ค)
๐ ๋ค์ด๋ด๋ฏน this ๋ฐ์ธ๋ฉ ์ด์?
์ผ๋ฐ ํจ์์ ๊ฒฝ์ฐ ๋ฉ์๋๋ก ํธ์ถ๋๋๋ / ์๋๋ฉด ํจ์ ์์ฒด๋ก ํธ์ถ๋๋๋์ ๋ฐ๋ผ ๋์ ์ผ๋ก this๊ฐ ๋ฐ์ธ๋ฉ๋ฉ๋๋ค.
JS์ this๋ ์๋ ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ฐ์ด ๋ฐ์ธ๋ฉ๋ ์ ์๋ค. ์ด ๋ฌธ์ ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ์คํํ ๋ ์๋๋ ๋๋ก ๋์์ํค๊ธฐ ์ํ์ฌ ์์ ์ค์ฝํ์ this๋ฅผ ์ฌ bind ์์ผ์ฃผ์ด์ผ ํ๋ ๋ฑ ๋ถํธํ๊ณ ๊ฐ๋ ์ฑ ๋์๊ฒ ๋ง๋๋ ์์ธ์ด ๋์์.
// ๋ฉ์๋๋ก ํธ์ถํ ๊ฒฝ์ฐ
var nameCard = {
name: "์ก๊ฐ",
addClickEvent: function () {
this.element = document.getElementById(this.name);
var logName = function () {
console.log("Hello! ", this);
};
// this.element.addEventListener("click", logName); // this.element ์ถ๋ ฅ
this.element.addEventListener("click", logName.bind(this)) // ํด๋น ์คํ๋ฌธ์ this(๋ฉ์๋ ํธ์ถ ๊ฐ์ฒด)๋ก ์ฌ๋ฐ์ธ๋ฉ ์์ผ์ผํจ
}
};
nameCard.addClickEvent();
๐ ์ด๋ป๊ฒ ํด๊ฒฐํ์๊น?
ํ์ง๋ง ํ์ดํ ํจ์์ ๋ฑ์ฅ์ผ๋ก, ํจ์๊ฐ ์ ์ธ๋ ์์ ์์ ๋ฐ๋ก ์์ ์ค์ฝํ์ this๋ก ๋ฐ์ธ๋ฉ ๋จ์ผ๋ก์จ ์๋์ฒ๋ผ ์ธ๋ถ bind ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ํ์๊ฐ ์์ด์ก๋ค.
const nameCard = {
name: "์ก๊ฐ",
addClickEvent: function () {
this.element = document.getElementById(this.name);
var logName = () => { // ํจ์๊ฐ ์ ์ธ๋ ์์ ์ ์์ ์ค์ฝํ์ this๋ก ์๋ ๋ฐ์ธ๋ฉ
console.log("Hello! ", this.name);
};
this.element.addEventListener("click", logName);
}
};
nameCard.addClickEvent();
โป ๋จ, ์ฃผ์ โป
์์ฑ์ ํจ์๋ new ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด ์์ฑ์๋ฅผ ์์ฑํจ. ํ์ง๋ง, ํ์ดํ ํจ์๋ ์์ฑ์ ํจ์๋ก ์ฌ์ฉํ ์ ์์.
new ์ฐ์ฐ์๋ ๋ค์์ ์๊ณ ๋ฆฌ์ฆ์ ๊ฑฐ์ณ this๋ฅผ ๋ฐํํ์ง๋ง, ํ์ดํ ํจ์๋ ์ฐธ์กฐํ๋ this ๊ฐ์ด ์คํ๋ฌธ ์ธ๋ถ ์๋จ์ this ๊ฐ์ด๋ฏ๋ก ๋ณธ๋ฌธ ๋ด ํ๋กํผํฐ๊ฐ ์ถ๊ฐ๋ ์ ์์.
- ๋น {} ๊ฐ์ฒด๊ฐ this์ ํ ๋น
2. ๊ทธ ๊ฐ์ฒด์ ์์ฑ์ ๋ด ๋ณธ๋ฌธ์ ์คํํ์ฌ ์๋ก์ด ํ๋กํผํฐ๋ฅผ ์ถ๊ฐํ์ฌ this๋ฅผ ์์
3. this๋ฅผ ๋ฐํ
const Human = () => {};
const human = new Human();
๐ ํผ๋์ ํด๋์ค ๊ตฌํ
๊ธฐ์กด ES5์๋ ํด๋์คํ ๋ฌธ๋ฒ ์์ด ํ๋กํ ํ์ ๊ฐ์ฒด๋ฅผ ํ์ฅํด ํด๋์ค๋ฅผ ํ๋ด๋ด์ด์์.
์ด๋ ์๋ ์์ ์ฒ๋ผ Person์ด ์ผ๋ฐ ํจ์์ธ์ง, ํด๋์ค ์์ฑ ํจ์์ธ์ง ํผ๋์ ์ผ์ผํค๊ณ , ๋ฉ์๋๊ฐ ๋ด๋ถ์ ์บก์ํ๋์ง ์์์ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง.
// ES5
function Person(name){
this.name = name;
}
Person.prototype.sayHi = function(){
console.log("Hi" + this.name);
}
var ์ก๊ฐ = new Person("์ก๊ฐ");
๐ ์ด๋ป๊ฒ ํด๊ฒฐํ์๊น?
ํด๋์ค ๋ฌธ๋ฒ์ ๋ณด๋ฉด ํด๋์ค ์์ฑ ํจ์์์ด ๋ถ๋ช ํ ๋ณด์ด๊ณ ์บก์ํ๋ ๋ชจ๋๋ค์ ํ์ธํ ์ ์์.
// ES6
class Person {
constructor(name){
this.name = name;
}
sayHi(){
console.log("Hi" + this.name);
}
}
const ์ก๊ฐ = new Person("์ก๊ฐ");
๐ ๊ทธ ์ธ ์ฐ๋ฆฌ๋ฅผ ์ํด ์ถ๊ฐ๋ ๊ธฐ๋ฅ๋ค
๊ฐ๋จํ๊ณ ํธํ ๊ฒ ์ข์!
a. ๋ฆฌํฐ๋ด
key์ value ๋ฆฌํฐ๋ด์ด ๊ฐ๋ค๋ฉด ํ ๋ฒ๋ง ์ ๋ ฅ ๊ฐ๋ฅ!
const dict = {name}; // == name:name
ํ ํ๋ฆฟ ๋ฆฌํฐ๋ด
console.log(`Hello ${brandName} ${productName}!`);
rest ํ๋ผ๋ฏธํฐ / spread ํํ์:(name, โฆrest) โ {console.log(rest)} / [โฆobj]
์ถ์ฝํ ๋ฉ์๋
// ES5
var nameCard = {
name: "์ก๊ฐ",
logName: function(){}
}
// ES6
var nameCard = {
name: "์ก๊ฐ",
logName(){}
}
b. ๊ตฌ๋ถํ + ์ธํ ๋ํดํธ๊ฐ ํ ๋น(Optional ์ฒ๋ฆฌ)
์๋ ์์ ์ฒ๋ผ ์ธํ์ ๋ํดํธ ๊ฐ์ ํ ๋นํ๊ณ ๊ตฌ๋ถํ ๋ก ๊ฐ์ ํธํ ๊บผ๋ด์ค ์ ์์.
function logHuman({
name = '์ก๊ฐ',
age = 23,
size = {
height: {hand: 0, feet: 0},
weight: {head: 0, body: 0}
}
} = {}) {
console.log(name, size.weight.head);
}
logHuman({
size: {height: {hand: 18, feet: 30}},
name: "์ก๊ฐํธ"
});
๋จ! ์์ ์ฒ๋ผ ์ธํ๊ณผ 2-depth ์ธํ์ด๋ฉด์, ๋ณด๋ด๋ ๋งค๊ฐ๋ณ์ size์ weight์ ์ ์ํด ์ฃผ๊ณ height์ ์ ์ํด์ฃผ์ง ์์ ์ฑ๋ก ๋๊ฒจ์ฃผ๋ ๊ฒฝ์ฐ,
๋งค๊ฐ๋ณ์์ ๋ํดํธ ๊ฐ์ด ์ค์ ๋์ง ์์ ์ฑ ๋ณด๋ด์ค ๋งค๊ฐ๋ณ์ ๊ฐ์ด ๋ค์ด๊ฐ๊ฒ ๋๋๋ฐ โ size.weight์ undefined ์ด๋ฏ๋ก weight.body ํ๋กํผํฐ๋ฅผ ์ฝ์ผ๋ ค ํ๊ฒ ๋๋ฉด ์ฐธ์กฐ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.?.์ผ๋ก ์ต์
๋ ์ฒ๋ฆฌ๋ฅผ ํด์ค ์ ์๋ค.
c. ์ ๋๋ ์ดํฐ Generator
์ ์ธ๋ฐฉ๋ฒ? Generator ์์ฑ์ || function* ์ฌ์ฉ.
์คํ ์ yield๋ฅผ ๋ง๋ ๋๊น์ง ์ฝ๋ ์ํ โ ๋ค์ ๋ผ์ธ์ผ๋ก ๋์ด๊ฐ. โ ์ฌ๊ฐ (์ ๋๋ ์ดํฐ. next()) โ ๋ค์ yield๋ฅผ ๋ง๋ ๋๊น์ง ์ํ
// ES6
function* gen(){
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}
const g = gen();
console.log(g.next()); // { value: 1, done: false }
console.log(g.next()); // { value: 2, done: false }
console.log(g.next()); // { value: 3, done: false }
console.log(g.next()); // { value: 4, done: false }
console.log(g.next()); // { value: 5, done: false }
console.log(g.next()); // { value: undefined, done: true }. done: true == ์ข
๋ฃ.
d. Named export
ํ ๋ชจ๋ ์์์ ๋ค๋ฅธ ๋ชจ๋์ ์ฌ์ฉํ๋ ค๋ฉด export๋ฅผ ํตํด ์ธ๋ถ ๋ชจ๋๋ก ์ ๊ทผํ ์ ์๊ฒ ๋ง๋ค์ด์ค๋ค.
export {human1, human2, human3}; // export
export default humanDefault
import {human1, human2, human3} __ from; // export
import humanDefault from __; // export default
import {human1 as a, human2 as b, human3 as c} from __; // ๊ฐ ๋ชจ๋์ alias
import * from __; // ์ ์ฒด ๋ชจ๋ import ํ ๊บผ๋ด ์ฐ๊ธฐ __.๋ชจ๋1
e. ๋น๋๊ธฐ ์ฒ๋ฆฌ
ES5์ ์ฝ๋ฐฑ ์ง์ฅ์ ES6์์ ๋ ๊ฐ์ง ๋ฐฉ์์ผ๋ก ํด๊ฒฐํฉ๋๋ค.
- Promise / then
์ฃผ๋ก ์๋ฒ์์ ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ํ๋ฉด์ ํ์ํ ๋ ์ฌ์ฉ.
promise์ ์ธ ๊ฐ์ง ์ํ: pending (๋น๋๊ธฐ ์ฒ๋ฆฌ ๋ก์ง์ด ์์ง ์๋ฃ๋์ง ์์ ์ํ), fulfilled (๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์๋ฃ๋์ด ํ๋ก๋ฏธ์ค๊ฐ ๊ฒฐ๊ด๊ฐ์ ๋ฐํํด ์ค ์ํ)/ rejected (๋น๋๊ธฐ ์ฒ๋ฆฌ๊ฐ ์คํจํ๊ฑฐ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ํ).
const p = new Promise((resolve, reject) => {
// ์ฑ๊ณตํ๋ฉด
resolve(๊ฒฐ๊ณผ๊ฐ);
// ์คํจ
reject(์คํจ);
// ์๋ฌ
throw new Error('์๋ฌ');
});
p.then(onFullFilled, onRejected).catch(errorCallback);
1.1. ๋ค์ค ํ๋ก๋ฏธ์ค ์ฒ๋ฆฌ
ํ๋ก๋ฏธ์ค๋ ๋จ์ผ ๋น๋๊ธฐ ์์ฒญ์ ์ฒ๋ฆฌํ๋๋ฐ, ์๋์ฒ๋ผ Promise.all์ด๋ Promise.race๋ฅผ ์ฌ์ฉํด ์ฌ๋ฌ ๊ฐ์ ๋น๋๊ธฐ ์์ฒญ์ ์ฒ๋ฆฌํ ์ ์๋ค.
var p1 = "promise ๋ฐํ api...์์ฒญ"
var p2 = 1337;
var p3 = "promise ๋ฐํ api...์์ฒญ"
Promise.all([p1, p2, p3]).then(values => {
console.log(values); // ๋ชจ๋ ํ๋ก๋ฏธ์ค๊ฐ resolve๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฐ ํ ๋ฐฐ์ด๋ก ๋ฐํ
});
Promise.race([p1, p2, p3]).then(value => {
console.log(value); // ๊ฐ์ฅ ๋จผ์ resolve๋ ๊ฐ ๋ฐํ
});
- async / await
๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ๋ ๋ ๋ค๋ฅธ ๋ฌธ๋ฒ์ ๋๋ค. async / await์ ์ฐ๋ฉด ๊ฐ๋ ์ฑ๋ ์ข๊ณ ์ดํดํ๊ธฐ๋ ํธํด ๋ณด์. async function ํจ์(){ try { await... // ๋น๋๊ธฐ์ฒ๋ฆฌํ ๊ตฌ๋ฌธ } catch(err) { } }
์... async-await ์ด ๊ฐ๋
์ฑ์ด ์ข๋ค๋ฉด, promise-then์ ์ ๊ณ์ ์ธ๊น?
async-await์ด ๋๊ฐ ๊ฐ๋
์ฑ์ด ์ข์ง๋ง, then ์ฒ๋ฆฌ๊ฐ ๋ ํธํ ๊ฒฝ์ฐ๋ ์์ต๋๋ค. ์๋์ ๊ฐ์ด ์ฐ์์ ์ธ ๋น๋๊ธฐ ์ฒ๋ฆฌ + ๊ฐ ๊ตฌ๋ฌธ๋ง๋ค ์๋ก ๋ค๋ฅธ ๋ก์ง์ ์ ์ฉํ๋ ๊ฒฝ์ฐ.
// then์ ์ฐ๋ ๊ฒฝ์ฐ...
const multiplyWithPromise = () => {
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve(1), 1000); // (*)
}).then((result) => { // (**)
console.log(result); // 1
return result * 2;
}).then((result) => { // (***)
console.log(result); // 2
return result * 2;
}).then((result) => {
console.log(result); // 4
return result * 2;
});
return promise;
}
multiplyWithPromise();
์ฐธ๊ณ ์๋ฃ:
https://ko.javascript.info/arrow-functions
https://ui.toast.com/fe-guide/ko_ES5-TO-ES6
https://sumini.dev/til/006-ecmascript/