[{"data":1,"prerenderedAt":1342},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjavascript-class-syntax-methods":3},{"id":4,"title":5,"body":6,"description":1327,"difficulty":1328,"extension":1329,"framework":1330,"frameworkSlug":1331,"meta":1332,"navigation":163,"order":58,"path":1333,"qaPath":1334,"seo":1335,"stem":1336,"subtopic":1337,"topic":1338,"topicSlug":1339,"updated":1340,"__hash__":1341},"blog\u002Fblog\u002Fjavascript-class-syntax-methods.md","JavaScript Class Syntax & Methods Explained — Fields, Getters, and the Prototype Truth",{"type":7,"value":8,"toc":1312},"minimark",[9,14,35,38,42,45,205,231,278,282,285,341,348,376,379,383,390,491,498,502,517,694,697,701,704,817,828,834,848,956,970,1067,1074,1078,1092,1098,1107,1157,1163,1167,1170,1255,1263,1267,1302,1308],[10,11,13],"h2",{"id":12},"classes-are-sugar-but-useful-sugar","Classes are sugar — but useful sugar",[15,16,17,18,22,23,27,28,30,31,34],"p",{},"JavaScript's ",[19,20,21],"code",{},"class"," keyword, added in ES2015, gives an object-oriented syntax that feels\nfamiliar to developers from Java, C#, or Python. But it's crucial to understand the headline\nfact up front: ",[24,25,26],"strong",{},"classes are syntactic sugar over constructor functions and prototypes.","\nThere's no new object model underneath — ",[19,29,21],{}," just makes the existing prototype machinery\ncleaner and less error-prone to write. Knowing this keeps you grounded: every class feature\nmaps to something you could write by hand with functions and ",[19,32,33],{},"prototype",".",[15,36,37],{},"That said, the sugar is genuinely valuable. It standardizes patterns, adds real\nencapsulation (private fields), and eliminates entire categories of bugs from the old\nmanual-wiring days.",[10,39,41],{"id":40},"declaring-a-class","Declaring a class",[15,43,44],{},"A class declaration bundles a constructor and methods into one block.",[46,47,52],"pre",{"className":48,"code":49,"language":50,"meta":51,"style":51},"language-js shiki shiki-themes github-light github-dark","class Circle {\n  constructor(radius) {\n    this.radius = radius          \u002F\u002F instance field set in constructor\n  }\n  area() {\n    return Math.PI * this.radius ** 2\n  }\n}\n\nconst c = new Circle(5)\nc.area()   \u002F\u002F 78.54...\n","js","",[19,53,54,70,86,106,112,121,147,152,158,165,190],{"__ignoreMap":51},[55,56,59,62,66],"span",{"class":57,"line":58},"line",1,[55,60,21],{"class":61},"szBVR",[55,63,65],{"class":64},"sScJk"," Circle",[55,67,69],{"class":68},"sVt8B"," {\n",[55,71,73,76,79,83],{"class":57,"line":72},2,[55,74,75],{"class":61},"  constructor",[55,77,78],{"class":68},"(",[55,80,82],{"class":81},"s4XuR","radius",[55,84,85],{"class":68},") {\n",[55,87,89,93,96,99,102],{"class":57,"line":88},3,[55,90,92],{"class":91},"sj4cs","    this",[55,94,95],{"class":68},".radius ",[55,97,98],{"class":61},"=",[55,100,101],{"class":68}," radius          ",[55,103,105],{"class":104},"sJ8bj","\u002F\u002F instance field set in constructor\n",[55,107,109],{"class":57,"line":108},4,[55,110,111],{"class":68},"  }\n",[55,113,115,118],{"class":57,"line":114},5,[55,116,117],{"class":64},"  area",[55,119,120],{"class":68},"() {\n",[55,122,124,127,130,133,136,139,141,144],{"class":57,"line":123},6,[55,125,126],{"class":61},"    return",[55,128,129],{"class":68}," Math.",[55,131,132],{"class":91},"PI",[55,134,135],{"class":61}," *",[55,137,138],{"class":91}," this",[55,140,95],{"class":68},[55,142,143],{"class":61},"**",[55,145,146],{"class":91}," 2\n",[55,148,150],{"class":57,"line":149},7,[55,151,111],{"class":68},[55,153,155],{"class":57,"line":154},8,[55,156,157],{"class":68},"}\n",[55,159,161],{"class":57,"line":160},9,[55,162,164],{"emptyLinePlaceholder":163},true,"\n",[55,166,168,171,174,177,180,182,184,187],{"class":57,"line":167},10,[55,169,170],{"class":61},"const",[55,172,173],{"class":91}," c",[55,175,176],{"class":61}," =",[55,178,179],{"class":61}," new",[55,181,65],{"class":64},[55,183,78],{"class":68},[55,185,186],{"class":91},"5",[55,188,189],{"class":68},")\n",[55,191,193,196,199,202],{"class":57,"line":192},11,[55,194,195],{"class":68},"c.",[55,197,198],{"class":64},"area",[55,200,201],{"class":68},"()   ",[55,203,204],{"class":104},"\u002F\u002F 78.54...\n",[15,206,207,208,211,212,215,216,218,219,222,223,226,227,230],{},"The ",[19,209,210],{},"constructor"," runs when you call ",[19,213,214],{},"new Circle(5)"," and initializes instance state. The\n",[19,217,198],{}," method is ",[24,220,221],{},"not"," copied onto each instance — it lives on ",[19,224,225],{},"Circle.prototype",", exactly\nas if you'd written ",[19,228,229],{},"Circle.prototype.area = function () {...}",". You can verify it:",[46,232,234],{"className":48,"code":233,"language":50,"meta":51,"style":51},"Object.getPrototypeOf(c) === Circle.prototype   \u002F\u002F true\nc.hasOwnProperty('area')                         \u002F\u002F false — it's on the prototype\n",[19,235,236,259],{"__ignoreMap":51},[55,237,238,241,244,247,250,252,254,256],{"class":57,"line":58},[55,239,240],{"class":68},"Object.",[55,242,243],{"class":64},"getPrototypeOf",[55,245,246],{"class":68},"(c) ",[55,248,249],{"class":61},"===",[55,251,65],{"class":91},[55,253,34],{"class":68},[55,255,33],{"class":91},[55,257,258],{"class":104},"   \u002F\u002F true\n",[55,260,261,263,266,268,272,275],{"class":57,"line":72},[55,262,195],{"class":68},[55,264,265],{"class":64},"hasOwnProperty",[55,267,78],{"class":68},[55,269,271],{"class":270},"sZZnC","'area'",[55,273,274],{"class":68},")                         ",[55,276,277],{"class":104},"\u002F\u002F false — it's on the prototype\n",[10,279,281],{"id":280},"class-declarations-vs-expressions","Class declarations vs expressions",[15,283,284],{},"Like functions, classes come in declaration and expression forms.",[46,286,288],{"className":48,"code":287,"language":50,"meta":51,"style":51},"class A {}                       \u002F\u002F declaration\nconst B = class {}               \u002F\u002F anonymous class expression\nconst C = class Named {}         \u002F\u002F named class expression\n",[19,289,290,303,321],{"__ignoreMap":51},[55,291,292,294,297,300],{"class":57,"line":58},[55,293,21],{"class":61},[55,295,296],{"class":64}," A",[55,298,299],{"class":68}," {}                       ",[55,301,302],{"class":104},"\u002F\u002F declaration\n",[55,304,305,307,310,312,315,318],{"class":57,"line":72},[55,306,170],{"class":61},[55,308,309],{"class":91}," B",[55,311,176],{"class":61},[55,313,314],{"class":61}," class",[55,316,317],{"class":68}," {}               ",[55,319,320],{"class":104},"\u002F\u002F anonymous class expression\n",[55,322,323,325,328,330,332,335,338],{"class":57,"line":88},[55,324,170],{"class":61},[55,326,327],{"class":91}," C",[55,329,176],{"class":61},[55,331,314],{"class":61},[55,333,334],{"class":64}," Named",[55,336,337],{"class":68}," {}         ",[55,339,340],{"class":104},"\u002F\u002F named class expression\n",[15,342,343,344,347],{},"One important difference from function declarations: ",[24,345,346],{},"classes are not hoisted in a usable\nway."," They live in a \"temporal dead zone\" until the declaration is evaluated, so you can't\nuse a class before you define it.",[46,349,351],{"className":48,"code":350,"language":50,"meta":51,"style":51},"new Foo()              \u002F\u002F ReferenceError — TDZ\nclass Foo {}\n",[19,352,353,367],{"__ignoreMap":51},[55,354,355,358,361,364],{"class":57,"line":58},[55,356,357],{"class":61},"new",[55,359,360],{"class":64}," Foo",[55,362,363],{"class":68},"()              ",[55,365,366],{"class":104},"\u002F\u002F ReferenceError — TDZ\n",[55,368,369,371,373],{"class":57,"line":72},[55,370,21],{"class":61},[55,372,360],{"class":64},[55,374,375],{"class":68}," {}\n",[15,377,378],{},"This stricter behavior is intentional — it prevents the confusing \"use before define\" that\nfunction hoisting allows.",[10,380,382],{"id":381},"instance-fields","Instance fields",[15,384,385,386,389],{},"Beyond setting fields in the constructor, you can declare ",[24,387,388],{},"class fields"," directly in the\nclass body. They're initialized on each instance before the constructor body runs.",[46,391,393],{"className":48,"code":392,"language":50,"meta":51,"style":51},"class Counter {\n  count = 0           \u002F\u002F instance field with a default\n  step = 1\n\n  increment() {\n    this.count += this.step\n    return this.count\n  }\n}\n\nnew Counter().increment()   \u002F\u002F 1\n",[19,394,395,404,417,427,431,438,453,462,466,470,474],{"__ignoreMap":51},[55,396,397,399,402],{"class":57,"line":58},[55,398,21],{"class":61},[55,400,401],{"class":64}," Counter",[55,403,69],{"class":68},[55,405,406,409,411,414],{"class":57,"line":72},[55,407,408],{"class":81},"  count",[55,410,176],{"class":61},[55,412,413],{"class":91}," 0",[55,415,416],{"class":104},"           \u002F\u002F instance field with a default\n",[55,418,419,422,424],{"class":57,"line":88},[55,420,421],{"class":81},"  step",[55,423,176],{"class":61},[55,425,426],{"class":91}," 1\n",[55,428,429],{"class":57,"line":108},[55,430,164],{"emptyLinePlaceholder":163},[55,432,433,436],{"class":57,"line":114},[55,434,435],{"class":64},"  increment",[55,437,120],{"class":68},[55,439,440,442,445,448,450],{"class":57,"line":123},[55,441,92],{"class":91},[55,443,444],{"class":68},".count ",[55,446,447],{"class":61},"+=",[55,449,138],{"class":91},[55,451,452],{"class":68},".step\n",[55,454,455,457,459],{"class":57,"line":149},[55,456,126],{"class":61},[55,458,138],{"class":91},[55,460,461],{"class":68},".count\n",[55,463,464],{"class":57,"line":154},[55,465,111],{"class":68},[55,467,468],{"class":57,"line":160},[55,469,157],{"class":68},[55,471,472],{"class":57,"line":167},[55,473,164],{"emptyLinePlaceholder":163},[55,475,476,478,480,483,486,488],{"class":57,"line":192},[55,477,357],{"class":61},[55,479,401],{"class":64},[55,481,482],{"class":68},"().",[55,484,485],{"class":64},"increment",[55,487,201],{"class":68},[55,489,490],{"class":104},"\u002F\u002F 1\n",[15,492,493,494,497],{},"Field declarations make defaults explicit and readable, and they're set per-instance (unlike\nmethods, which are shared). A subtle point: a field initializer that references ",[19,495,496],{},"this"," runs\nin field-declaration order, so later fields can build on earlier ones.",[10,499,501],{"id":500},"methods-getters-and-setters","Methods, getters, and setters",[15,503,504,505,508,509,512,513,516],{},"Methods defined in the class body land on the prototype. You can also define ",[24,506,507],{},"accessor\nproperties"," with ",[19,510,511],{},"get"," and ",[19,514,515],{},"set",", which look like fields but run functions.",[46,518,520],{"className":48,"code":519,"language":50,"meta":51,"style":51},"class Temperature {\n  constructor(celsius) { this.celsius = celsius }\n\n  get fahrenheit() { return this.celsius * 9 \u002F 5 + 32 }\n  set fahrenheit(f) { this.celsius = (f - 32) * 5 \u002F 9 }\n}\n\nconst t = new Temperature(20)\nt.fahrenheit          \u002F\u002F 68   — getter\nt.fahrenheit = 212    \u002F\u002F setter\nt.celsius             \u002F\u002F 100\n",[19,521,522,531,553,557,596,637,641,645,665,673,686],{"__ignoreMap":51},[55,523,524,526,529],{"class":57,"line":58},[55,525,21],{"class":61},[55,527,528],{"class":64}," Temperature",[55,530,69],{"class":68},[55,532,533,535,537,540,543,545,548,550],{"class":57,"line":72},[55,534,75],{"class":61},[55,536,78],{"class":68},[55,538,539],{"class":81},"celsius",[55,541,542],{"class":68},") { ",[55,544,496],{"class":91},[55,546,547],{"class":68},".celsius ",[55,549,98],{"class":61},[55,551,552],{"class":68}," celsius }\n",[55,554,555],{"class":57,"line":88},[55,556,164],{"emptyLinePlaceholder":163},[55,558,559,562,565,568,571,573,575,578,581,584,587,590,593],{"class":57,"line":108},[55,560,561],{"class":61},"  get",[55,563,564],{"class":64}," fahrenheit",[55,566,567],{"class":68},"() { ",[55,569,570],{"class":61},"return",[55,572,138],{"class":91},[55,574,547],{"class":68},[55,576,577],{"class":61},"*",[55,579,580],{"class":91}," 9",[55,582,583],{"class":61}," \u002F",[55,585,586],{"class":91}," 5",[55,588,589],{"class":61}," +",[55,591,592],{"class":91}," 32",[55,594,595],{"class":68}," }\n",[55,597,598,601,603,605,608,610,612,614,616,619,622,624,627,629,631,633,635],{"class":57,"line":114},[55,599,600],{"class":61},"  set",[55,602,564],{"class":64},[55,604,78],{"class":68},[55,606,607],{"class":81},"f",[55,609,542],{"class":68},[55,611,496],{"class":91},[55,613,547],{"class":68},[55,615,98],{"class":61},[55,617,618],{"class":68}," (f ",[55,620,621],{"class":61},"-",[55,623,592],{"class":91},[55,625,626],{"class":68},") ",[55,628,577],{"class":61},[55,630,586],{"class":91},[55,632,583],{"class":61},[55,634,580],{"class":91},[55,636,595],{"class":68},[55,638,639],{"class":57,"line":123},[55,640,157],{"class":68},[55,642,643],{"class":57,"line":149},[55,644,164],{"emptyLinePlaceholder":163},[55,646,647,649,652,654,656,658,660,663],{"class":57,"line":154},[55,648,170],{"class":61},[55,650,651],{"class":91}," t",[55,653,176],{"class":61},[55,655,179],{"class":61},[55,657,528],{"class":64},[55,659,78],{"class":68},[55,661,662],{"class":91},"20",[55,664,189],{"class":68},[55,666,667,670],{"class":57,"line":160},[55,668,669],{"class":68},"t.fahrenheit          ",[55,671,672],{"class":104},"\u002F\u002F 68   — getter\n",[55,674,675,678,680,683],{"class":57,"line":167},[55,676,677],{"class":68},"t.fahrenheit ",[55,679,98],{"class":61},[55,681,682],{"class":91}," 212",[55,684,685],{"class":104},"    \u002F\u002F setter\n",[55,687,688,691],{"class":57,"line":192},[55,689,690],{"class":68},"t.celsius             ",[55,692,693],{"class":104},"\u002F\u002F 100\n",[15,695,696],{},"Getters and setters are ideal for derived values and validation. Like methods, they live on\nthe prototype, so all instances share the accessor functions.",[10,698,700],{"id":699},"computed-method-names","Computed method names",[15,702,703],{},"Method names can be computed with brackets, just like object literal keys — useful for\ndynamic or symbol-based methods.",[46,705,707],{"className":48,"code":706,"language":50,"meta":51,"style":51},"const sym = Symbol('run')\nconst methodName = 'go'\n\nclass Machine {\n  [methodName]() { return 'going' }      \u002F\u002F computed string name\n  [sym]() { return 'running' }           \u002F\u002F symbol-keyed method\n  *[Symbol.iterator]() { yield 1; yield 2 }  \u002F\u002F makes instances iterable\n}\n",[19,708,709,728,740,744,753,769,785,813],{"__ignoreMap":51},[55,710,711,713,716,718,721,723,726],{"class":57,"line":58},[55,712,170],{"class":61},[55,714,715],{"class":91}," sym",[55,717,176],{"class":61},[55,719,720],{"class":64}," Symbol",[55,722,78],{"class":68},[55,724,725],{"class":270},"'run'",[55,727,189],{"class":68},[55,729,730,732,735,737],{"class":57,"line":72},[55,731,170],{"class":61},[55,733,734],{"class":91}," methodName",[55,736,176],{"class":61},[55,738,739],{"class":270}," 'go'\n",[55,741,742],{"class":57,"line":88},[55,743,164],{"emptyLinePlaceholder":163},[55,745,746,748,751],{"class":57,"line":108},[55,747,21],{"class":61},[55,749,750],{"class":64}," Machine",[55,752,69],{"class":68},[55,754,755,758,760,763,766],{"class":57,"line":114},[55,756,757],{"class":68},"  [methodName]() { ",[55,759,570],{"class":61},[55,761,762],{"class":270}," 'going'",[55,764,765],{"class":68}," }      ",[55,767,768],{"class":104},"\u002F\u002F computed string name\n",[55,770,771,774,776,779,782],{"class":57,"line":123},[55,772,773],{"class":68},"  [sym]() { ",[55,775,570],{"class":61},[55,777,778],{"class":270}," 'running'",[55,780,781],{"class":68}," }           ",[55,783,784],{"class":104},"\u002F\u002F symbol-keyed method\n",[55,786,787,790,793,796,799,802,804,807,810],{"class":57,"line":149},[55,788,789],{"class":61},"  *",[55,791,792],{"class":68},"[Symbol.iterator]() { ",[55,794,795],{"class":61},"yield",[55,797,798],{"class":91}," 1",[55,800,801],{"class":68},"; ",[55,803,795],{"class":61},[55,805,806],{"class":91}," 2",[55,808,809],{"class":68}," }  ",[55,811,812],{"class":104},"\u002F\u002F makes instances iterable\n",[55,814,815],{"class":57,"line":154},[55,816,157],{"class":68},[15,818,819,820,823,824,827],{},"Defining ",[19,821,822],{},"[Symbol.iterator]"," as a generator method is the idiomatic way to make a class's\ninstances work with ",[19,825,826],{},"for...of"," and spread.",[10,829,831,833],{"id":830},"this-inside-methods",[19,832,496],{}," inside methods",[15,835,836,837,839,840,844,845,847],{},"A method's ",[19,838,496],{}," is the instance it was called on — but only if you call it ",[841,842,843],"em",{},"as a method",".\nDetach it and ",[19,846,496],{}," is lost, the same gotcha as with any function.",[46,849,851],{"className":48,"code":850,"language":50,"meta":51,"style":51},"class Button {\n  constructor(label) { this.label = label }\n  click() { return `${this.label} clicked` }\n}\n\nconst b = new Button('OK')\nconst fn = b.click\nfn()   \u002F\u002F TypeError — `this` is undefined (class bodies are strict mode)\n",[19,852,853,862,883,906,910,914,934,946],{"__ignoreMap":51},[55,854,855,857,860],{"class":57,"line":58},[55,856,21],{"class":61},[55,858,859],{"class":64}," Button",[55,861,69],{"class":68},[55,863,864,866,868,871,873,875,878,880],{"class":57,"line":72},[55,865,75],{"class":61},[55,867,78],{"class":68},[55,869,870],{"class":81},"label",[55,872,542],{"class":68},[55,874,496],{"class":91},[55,876,877],{"class":68},".label ",[55,879,98],{"class":61},[55,881,882],{"class":68}," label }\n",[55,884,885,888,890,892,895,897,899,901,904],{"class":57,"line":88},[55,886,887],{"class":64},"  click",[55,889,567],{"class":68},[55,891,570],{"class":61},[55,893,894],{"class":270}," `${",[55,896,496],{"class":91},[55,898,34],{"class":270},[55,900,870],{"class":68},[55,902,903],{"class":270},"} clicked`",[55,905,595],{"class":68},[55,907,908],{"class":57,"line":108},[55,909,157],{"class":68},[55,911,912],{"class":57,"line":114},[55,913,164],{"emptyLinePlaceholder":163},[55,915,916,918,921,923,925,927,929,932],{"class":57,"line":123},[55,917,170],{"class":61},[55,919,920],{"class":91}," b",[55,922,176],{"class":61},[55,924,179],{"class":61},[55,926,859],{"class":64},[55,928,78],{"class":68},[55,930,931],{"class":270},"'OK'",[55,933,189],{"class":68},[55,935,936,938,941,943],{"class":57,"line":149},[55,937,170],{"class":61},[55,939,940],{"class":91}," fn",[55,942,176],{"class":61},[55,944,945],{"class":68}," b.click\n",[55,947,948,951,953],{"class":57,"line":154},[55,949,950],{"class":64},"fn",[55,952,201],{"class":68},[55,954,955],{"class":104},"\u002F\u002F TypeError — `this` is undefined (class bodies are strict mode)\n",[15,957,958,959,962,963,966,967,969],{},"Two common fixes: bind in the constructor (",[19,960,961],{},"this.click = this.click.bind(this)",") or use a\n",[24,964,965],{},"field with an arrow function",", which captures ",[19,968,496],{}," lexically.",[46,971,973],{"className":48,"code":972,"language":50,"meta":51,"style":51},"class Button {\n  constructor(label) { this.label = label }\n  click = () => `${this.label} clicked`   \u002F\u002F arrow field — `this` always bound\n}\nconst b = new Button('OK')\nconst fn = b.click\nfn()   \u002F\u002F 'OK clicked' — works detached\n",[19,974,975,983,1001,1026,1030,1048,1058],{"__ignoreMap":51},[55,976,977,979,981],{"class":57,"line":58},[55,978,21],{"class":61},[55,980,859],{"class":64},[55,982,69],{"class":68},[55,984,985,987,989,991,993,995,997,999],{"class":57,"line":72},[55,986,75],{"class":61},[55,988,78],{"class":68},[55,990,870],{"class":81},[55,992,542],{"class":68},[55,994,496],{"class":91},[55,996,877],{"class":68},[55,998,98],{"class":61},[55,1000,882],{"class":68},[55,1002,1003,1005,1007,1010,1013,1015,1017,1019,1021,1023],{"class":57,"line":88},[55,1004,887],{"class":64},[55,1006,176],{"class":61},[55,1008,1009],{"class":68}," () ",[55,1011,1012],{"class":61},"=>",[55,1014,894],{"class":270},[55,1016,496],{"class":91},[55,1018,34],{"class":270},[55,1020,870],{"class":68},[55,1022,903],{"class":270},[55,1024,1025],{"class":104},"   \u002F\u002F arrow field — `this` always bound\n",[55,1027,1028],{"class":57,"line":108},[55,1029,157],{"class":68},[55,1031,1032,1034,1036,1038,1040,1042,1044,1046],{"class":57,"line":114},[55,1033,170],{"class":61},[55,1035,920],{"class":91},[55,1037,176],{"class":61},[55,1039,179],{"class":61},[55,1041,859],{"class":64},[55,1043,78],{"class":68},[55,1045,931],{"class":270},[55,1047,189],{"class":68},[55,1049,1050,1052,1054,1056],{"class":57,"line":123},[55,1051,170],{"class":61},[55,1053,940],{"class":91},[55,1055,176],{"class":61},[55,1057,945],{"class":68},[55,1059,1060,1062,1064],{"class":57,"line":149},[55,1061,950],{"class":64},[55,1063,201],{"class":68},[55,1065,1066],{"class":104},"\u002F\u002F 'OK clicked' — works detached\n",[15,1068,1069,1070,1073],{},"The tradeoff: arrow-function fields are created ",[24,1071,1072],{},"per instance"," (not shared on the\nprototype), costing a bit more memory. For event handlers that get passed around, that's\nusually a worthwhile trade.",[10,1075,1077],{"id":1076},"strict-mode-by-default","Strict mode by default",[15,1079,1080,1081,1084,1085,1088,1089,1091],{},"Everything inside a class body runs in ",[24,1082,1083],{},"strict mode"," automatically, regardless of the\nsurrounding code. That's why detached methods get ",[19,1086,1087],{},"undefined"," for ",[19,1090,496],{}," instead of the\nglobal object, and why silent failures (like writing to a read-only property) become loud\nerrors. This stricter default catches bugs early.",[10,1093,1095,1096],{"id":1094},"classes-must-be-called-with-new","Classes must be called with ",[19,1097,357],{},[15,1099,1100,1101,1104,1105,34],{},"Unlike old constructor functions, a class ",[24,1102,1103],{},"throws"," if you forget ",[19,1106,357],{},[46,1108,1110],{"className":48,"code":1109,"language":50,"meta":51,"style":51},"class User { constructor(name) { this.name = name } }\nUser('Ada')   \u002F\u002F TypeError: Class constructor User cannot be invoked without 'new'\n",[19,1111,1112,1141],{"__ignoreMap":51},[55,1113,1114,1116,1119,1122,1124,1126,1129,1131,1133,1136,1138],{"class":57,"line":58},[55,1115,21],{"class":61},[55,1117,1118],{"class":64}," User",[55,1120,1121],{"class":68}," { ",[55,1123,210],{"class":61},[55,1125,78],{"class":68},[55,1127,1128],{"class":81},"name",[55,1130,542],{"class":68},[55,1132,496],{"class":91},[55,1134,1135],{"class":68},".name ",[55,1137,98],{"class":61},[55,1139,1140],{"class":68}," name } }\n",[55,1142,1143,1146,1148,1151,1154],{"class":57,"line":72},[55,1144,1145],{"class":64},"User",[55,1147,78],{"class":68},[55,1149,1150],{"class":270},"'Ada'",[55,1152,1153],{"class":68},")   ",[55,1155,1156],{"class":104},"\u002F\u002F TypeError: Class constructor User cannot be invoked without 'new'\n",[15,1158,1159,1160,1162],{},"This is a feature: it eliminates the silent forgotten-",[19,1161,357],{}," bug that plagued constructor\nfunctions. There's no way to accidentally pollute the global object with a class.",[10,1164,1166],{"id":1165},"what-it-compiles-to","What it compiles to",[15,1168,1169],{},"To cement the \"sugar\" point, here's the rough equivalent of a simple class written the old\nway:",[46,1171,1173],{"className":48,"code":1172,"language":50,"meta":51,"style":51},"\u002F\u002F class Circle { constructor(r){ this.r = r } area(){ return Math.PI*this.r**2 } }\nfunction Circle(r) {\n  'use strict'\n  this.r = r\n}\nCircle.prototype.area = function () { return Math.PI * this.r ** 2 }\n",[19,1174,1175,1180,1194,1199,1212,1216],{"__ignoreMap":51},[55,1176,1177],{"class":57,"line":58},[55,1178,1179],{"class":104},"\u002F\u002F class Circle { constructor(r){ this.r = r } area(){ return Math.PI*this.r**2 } }\n",[55,1181,1182,1185,1187,1189,1192],{"class":57,"line":72},[55,1183,1184],{"class":61},"function",[55,1186,65],{"class":64},[55,1188,78],{"class":68},[55,1190,1191],{"class":81},"r",[55,1193,85],{"class":68},[55,1195,1196],{"class":57,"line":88},[55,1197,1198],{"class":270},"  'use strict'\n",[55,1200,1201,1204,1207,1209],{"class":57,"line":108},[55,1202,1203],{"class":91},"  this",[55,1205,1206],{"class":68},".r ",[55,1208,98],{"class":61},[55,1210,1211],{"class":68}," r\n",[55,1213,1214],{"class":57,"line":114},[55,1215,157],{"class":68},[55,1217,1218,1221,1223,1225,1227,1229,1231,1234,1237,1239,1241,1243,1245,1247,1249,1251,1253],{"class":57,"line":123},[55,1219,1220],{"class":91},"Circle",[55,1222,34],{"class":68},[55,1224,33],{"class":91},[55,1226,34],{"class":68},[55,1228,198],{"class":64},[55,1230,176],{"class":61},[55,1232,1233],{"class":61}," function",[55,1235,1236],{"class":68}," () { ",[55,1238,570],{"class":61},[55,1240,129],{"class":68},[55,1242,132],{"class":91},[55,1244,135],{"class":61},[55,1246,138],{"class":91},[55,1248,1206],{"class":68},[55,1250,143],{"class":61},[55,1252,806],{"class":91},[55,1254,595],{"class":68},[15,1256,207,1257,1259,1260,1262],{},[19,1258,21],{}," version adds the must-use-",[19,1261,357],{}," guard, strict mode, and cleaner syntax — but the\nprototype-based result is identical. Whenever class behavior puzzles you, mentally translate\nit back to constructors and prototypes and the answer usually appears.",[10,1264,1266],{"id":1265},"key-takeaways","Key takeaways",[1268,1269,1270,1276,1279,1282,1287,1296],"ul",{},[1271,1272,1273,1275],"li",{},[19,1274,21],{}," is syntactic sugar over constructor functions and prototypes — no new object model.",[1271,1277,1278],{},"Methods, getters, and setters live on the prototype and are shared; instance fields are\nper-instance.",[1271,1280,1281],{},"Class bodies are always strict mode, and classes can't be used before declaration (TDZ).",[1271,1283,1284,1286],{},[19,1285,496],{}," follows normal rules — detached methods lose it; arrow-function fields capture it\nlexically at a per-instance memory cost.",[1271,1288,1289,1290,1292,1293,1295],{},"Classes throw if called without ",[19,1291,357],{},", eliminating the forgotten-",[19,1294,357],{}," bug.",[1271,1297,1298,1299,1301],{},"Computed names and ",[19,1300,822],{}," generator methods enable dynamic and iterable\nclasses.",[15,1303,1304,1305,1307],{},"Treat ",[19,1306,21],{}," as a clean, safer wrapper over the prototype system you already understand, and\nits every behavior becomes predictable rather than magical.",[1309,1310,1311],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":51,"searchDepth":72,"depth":72,"links":1313},[1314,1315,1316,1317,1318,1319,1320,1322,1323,1325,1326],{"id":12,"depth":72,"text":13},{"id":40,"depth":72,"text":41},{"id":280,"depth":72,"text":281},{"id":381,"depth":72,"text":382},{"id":500,"depth":72,"text":501},{"id":699,"depth":72,"text":700},{"id":830,"depth":72,"text":1321},"this inside methods",{"id":1076,"depth":72,"text":1077},{"id":1094,"depth":72,"text":1324},"Classes must be called with new",{"id":1165,"depth":72,"text":1166},{"id":1265,"depth":72,"text":1266},"A complete guide to JavaScript class syntax — constructors, methods, fields, getters and setters, and what classes really compile to under the hood.","medium","md","JavaScript","javascript",{},"\u002Fblog\u002Fjavascript-class-syntax-methods","\u002Fjavascript\u002Fclasses\u002Fclass-syntax",{"title":5,"description":1327},"blog\u002Fjavascript-class-syntax-methods","Class Syntax & Methods","Classes & OOP","classes","2026-06-18","-DQH0PwSFNa6TkwTKSOsYp7DCZiwHOG-QoJdWb2009Y",1781808673080]