[{"data":1,"prerenderedAt":1469},["ShallowReactive",2],{"blog-\u002Fblog\u002Fjavascript-new-operator-constructor-functions":3},{"id":4,"title":5,"body":6,"description":1454,"difficulty":1455,"extension":1456,"framework":1457,"frameworkSlug":1458,"meta":1459,"navigation":280,"order":221,"path":1460,"qaPath":1461,"seo":1462,"stem":1463,"subtopic":1464,"topic":1465,"topicSlug":1466,"updated":1467,"__hash__":1468},"blog\u002Fblog\u002Fjavascript-new-operator-constructor-functions.md","The new Operator & Constructor Functions in JavaScript — How Object Creation Really Works",{"type":7,"value":8,"toc":1436},"minimark",[9,19,42,61,67,74,118,121,326,337,341,347,516,522,526,540,634,646,653,669,753,769,775,788,869,883,964,968,973,1118,1124,1128,1138,1195,1208,1212,1232,1313,1325,1332,1356,1360,1426,1432],[10,11,13,14,18],"h2",{"id":12},"what-new-really-does","What ",[15,16,17],"code",{},"new"," really does",[20,21,22,23,26,27,29,30,34,35,38,39,41],"p",{},"You write ",[15,24,25],{},"new Dog('Rex')"," thousands of times, but what does the ",[15,28,17],{}," operator ",[31,32,33],"em",{},"actually","\ndo? It's not magic — it's four well-defined steps, and knowing them demystifies\nconstructors, the ",[15,36,37],{},"class"," keyword, and a whole category of bugs. When you understand ",[15,40,17],{},",\nyou understand how JavaScript turns a plain function into an object factory.",[20,43,44,45,49,50,52,53,56,57,60],{},"A ",[46,47,48],"strong",{},"constructor function"," is just a normal function intended to be called with ",[15,51,17],{},".\nConvention capitalizes its name (",[15,54,55],{},"Dog",", not ",[15,58,59],{},"dog",") to signal that intent.",[10,62,64,65],{"id":63},"the-four-steps-of-new","The four steps of ",[15,66,17],{},[20,68,69,70,73],{},"When you evaluate ",[15,71,72],{},"new Fn(args)",", the engine performs these steps:",[75,76,77,84,94,108],"ol",{},[78,79,80,83],"li",{},[46,81,82],{},"Create"," a brand-new empty object.",[78,85,86,89,90,93],{},[46,87,88],{},"Link"," that object's prototype to ",[15,91,92],{},"Fn.prototype",".",[78,95,96,99,100,103,104,107],{},[46,97,98],{},"Call"," ",[15,101,102],{},"Fn"," with ",[15,105,106],{},"this"," bound to the new object, passing the arguments.",[78,109,110,113,114,117],{},[46,111,112],{},"Return"," the new object — ",[31,115,116],{},"unless"," the constructor explicitly returns its own object.",[20,119,120],{},"You can replicate it by hand to see there's nothing hidden:",[122,123,128],"pre",{"className":124,"code":125,"language":126,"meta":127,"style":127},"language-js shiki shiki-themes github-light github-dark","function myNew(Fn, ...args) {\n  const obj = Object.create(Fn.prototype)   \u002F\u002F steps 1 + 2\n  const result = Fn.apply(obj, args)        \u002F\u002F step 3\n  return (typeof result === 'object' && result !== null) ? result : obj  \u002F\u002F step 4\n}\n\nfunction Dog(name) { this.name = name }\nmyNew(Dog, 'Rex')   \u002F\u002F { name: 'Rex' } same as new Dog('Rex')\n","js","",[15,129,130,162,197,219,269,275,282,309],{"__ignoreMap":127},[131,132,135,139,143,147,150,153,156,159],"span",{"class":133,"line":134},"line",1,[131,136,138],{"class":137},"szBVR","function",[131,140,142],{"class":141},"sScJk"," myNew",[131,144,146],{"class":145},"sVt8B","(",[131,148,102],{"class":149},"s4XuR",[131,151,152],{"class":145},", ",[131,154,155],{"class":137},"...",[131,157,158],{"class":149},"args",[131,160,161],{"class":145},") {\n",[131,163,165,168,172,175,178,181,183,185,187,190,193],{"class":133,"line":164},2,[131,166,167],{"class":137},"  const",[131,169,171],{"class":170},"sj4cs"," obj",[131,173,174],{"class":137}," =",[131,176,177],{"class":145}," Object.",[131,179,180],{"class":141},"create",[131,182,146],{"class":145},[131,184,102],{"class":170},[131,186,93],{"class":145},[131,188,189],{"class":170},"prototype",[131,191,192],{"class":145},")   ",[131,194,196],{"class":195},"sJ8bj","\u002F\u002F steps 1 + 2\n",[131,198,200,202,205,207,210,213,216],{"class":133,"line":199},3,[131,201,167],{"class":137},[131,203,204],{"class":170}," result",[131,206,174],{"class":137},[131,208,209],{"class":145}," Fn.",[131,211,212],{"class":141},"apply",[131,214,215],{"class":145},"(obj, args)        ",[131,217,218],{"class":195},"\u002F\u002F step 3\n",[131,220,222,225,228,231,234,237,241,244,246,249,252,255,258,260,263,266],{"class":133,"line":221},4,[131,223,224],{"class":137},"  return",[131,226,227],{"class":145}," (",[131,229,230],{"class":137},"typeof",[131,232,233],{"class":145}," result ",[131,235,236],{"class":137},"===",[131,238,240],{"class":239},"sZZnC"," 'object'",[131,242,243],{"class":137}," &&",[131,245,233],{"class":145},[131,247,248],{"class":137},"!==",[131,250,251],{"class":170}," null",[131,253,254],{"class":145},") ",[131,256,257],{"class":137},"?",[131,259,233],{"class":145},[131,261,262],{"class":137},":",[131,264,265],{"class":145}," obj  ",[131,267,268],{"class":195},"\u002F\u002F step 4\n",[131,270,272],{"class":133,"line":271},5,[131,273,274],{"class":145},"}\n",[131,276,278],{"class":133,"line":277},6,[131,279,281],{"emptyLinePlaceholder":280},true,"\n",[131,283,285,287,290,292,295,298,300,303,306],{"class":133,"line":284},7,[131,286,138],{"class":137},[131,288,289],{"class":141}," Dog",[131,291,146],{"class":145},[131,293,294],{"class":149},"name",[131,296,297],{"class":145},") { ",[131,299,106],{"class":170},[131,301,302],{"class":145},".name ",[131,304,305],{"class":137},"=",[131,307,308],{"class":145}," name }\n",[131,310,312,315,318,321,323],{"class":133,"line":311},8,[131,313,314],{"class":141},"myNew",[131,316,317],{"class":145},"(Dog, ",[131,319,320],{"class":239},"'Rex'",[131,322,192],{"class":145},[131,324,325],{"class":195},"\u002F\u002F { name: 'Rex' } same as new Dog('Rex')\n",[20,327,328,329,332,333,336],{},"That ",[15,330,331],{},"Object.create(Fn.prototype)"," is exactly why instances inherit the constructor's\nprototype methods, and why ",[15,334,335],{},"instanceof"," works.",[10,338,340],{"id":339},"building-objects-with-a-constructor","Building objects with a constructor",[20,342,343,344,346],{},"A constructor's job is to initialize the new object's own state via ",[15,345,106],{},". Shared methods\ngo on the prototype so all instances share them.",[122,348,350],{"className":124,"code":349,"language":126,"meta":127,"style":127},"function Circle(radius) {\n  this.radius = radius        \u002F\u002F per-instance data\n}\nCircle.prototype.area = function () {\n  return Math.PI * this.radius ** 2   \u002F\u002F shared behavior\n}\n\nconst c = new Circle(5)\nc.area()                 \u002F\u002F 78.54...\nc instanceof Circle      \u002F\u002F true\nObject.getPrototypeOf(c) === Circle.prototype   \u002F\u002F true\n",[15,351,352,366,382,386,408,435,439,443,466,480,493],{"__ignoreMap":127},[131,353,354,356,359,361,364],{"class":133,"line":134},[131,355,138],{"class":137},[131,357,358],{"class":141}," Circle",[131,360,146],{"class":145},[131,362,363],{"class":149},"radius",[131,365,161],{"class":145},[131,367,368,371,374,376,379],{"class":133,"line":164},[131,369,370],{"class":170},"  this",[131,372,373],{"class":145},".radius ",[131,375,305],{"class":137},[131,377,378],{"class":145}," radius        ",[131,380,381],{"class":195},"\u002F\u002F per-instance data\n",[131,383,384],{"class":133,"line":199},[131,385,274],{"class":145},[131,387,388,391,393,395,397,400,402,405],{"class":133,"line":221},[131,389,390],{"class":170},"Circle",[131,392,93],{"class":145},[131,394,189],{"class":170},[131,396,93],{"class":145},[131,398,399],{"class":141},"area",[131,401,174],{"class":137},[131,403,404],{"class":137}," function",[131,406,407],{"class":145}," () {\n",[131,409,410,412,415,418,421,424,426,429,432],{"class":133,"line":271},[131,411,224],{"class":137},[131,413,414],{"class":145}," Math.",[131,416,417],{"class":170},"PI",[131,419,420],{"class":137}," *",[131,422,423],{"class":170}," this",[131,425,373],{"class":145},[131,427,428],{"class":137},"**",[131,430,431],{"class":170}," 2",[131,433,434],{"class":195},"   \u002F\u002F shared behavior\n",[131,436,437],{"class":133,"line":277},[131,438,274],{"class":145},[131,440,441],{"class":133,"line":284},[131,442,281],{"emptyLinePlaceholder":280},[131,444,445,448,451,453,456,458,460,463],{"class":133,"line":311},[131,446,447],{"class":137},"const",[131,449,450],{"class":170}," c",[131,452,174],{"class":137},[131,454,455],{"class":137}," new",[131,457,358],{"class":141},[131,459,146],{"class":145},[131,461,462],{"class":170},"5",[131,464,465],{"class":145},")\n",[131,467,469,472,474,477],{"class":133,"line":468},9,[131,470,471],{"class":145},"c.",[131,473,399],{"class":141},[131,475,476],{"class":145},"()                 ",[131,478,479],{"class":195},"\u002F\u002F 78.54...\n",[131,481,483,486,488,490],{"class":133,"line":482},10,[131,484,485],{"class":145},"c ",[131,487,335],{"class":137},[131,489,358],{"class":141},[131,491,492],{"class":195},"      \u002F\u002F true\n",[131,494,496,499,502,505,507,509,511,513],{"class":133,"line":495},11,[131,497,498],{"class":145},"Object.",[131,500,501],{"class":141},"getPrototypeOf",[131,503,504],{"class":145},"(c) ",[131,506,236],{"class":137},[131,508,358],{"class":170},[131,510,93],{"class":145},[131,512,189],{"class":170},[131,514,515],{"class":195},"   \u002F\u002F true\n",[20,517,518,519,521],{},"Putting ",[15,520,399],{}," on the prototype rather than inside the constructor means all circles share\none function object — important when you create many instances.",[10,523,525],{"id":524},"the-return-value-rule","The return-value rule",[20,527,528,529,532,533,535,536,539],{},"Step 4 has a subtlety: if the constructor explicitly returns an ",[46,530,531],{},"object",", that object\nreplaces the freshly-created ",[15,534,106],{},". If it returns a ",[46,537,538],{},"primitive"," (or nothing), the new\nobject is used as normal.",[122,541,543],{"className":124,"code":542,"language":126,"meta":127,"style":127},"function A() { this.x = 1; return { x: 99 } }\nnew A().x   \u002F\u002F 99  — object return overrides `this` surprising\n\nfunction B() { this.x = 1; return 42 }\nnew B().x   \u002F\u002F 1   — primitive return ignored\n",[15,544,545,580,592,596,623],{"__ignoreMap":127},[131,546,547,549,552,555,557,560,562,565,568,571,574,577],{"class":133,"line":134},[131,548,138],{"class":137},[131,550,551],{"class":141}," A",[131,553,554],{"class":145},"() { ",[131,556,106],{"class":170},[131,558,559],{"class":145},".x ",[131,561,305],{"class":137},[131,563,564],{"class":170}," 1",[131,566,567],{"class":145},"; ",[131,569,570],{"class":137},"return",[131,572,573],{"class":145}," { x: ",[131,575,576],{"class":170},"99",[131,578,579],{"class":145}," } }\n",[131,581,582,584,586,589],{"class":133,"line":164},[131,583,17],{"class":137},[131,585,551],{"class":141},[131,587,588],{"class":145},"().x   ",[131,590,591],{"class":195},"\u002F\u002F 99  — object return overrides `this` surprising\n",[131,593,594],{"class":133,"line":199},[131,595,281],{"emptyLinePlaceholder":280},[131,597,598,600,603,605,607,609,611,613,615,617,620],{"class":133,"line":221},[131,599,138],{"class":137},[131,601,602],{"class":141}," B",[131,604,554],{"class":145},[131,606,106],{"class":170},[131,608,559],{"class":145},[131,610,305],{"class":137},[131,612,564],{"class":170},[131,614,567],{"class":145},[131,616,570],{"class":137},[131,618,619],{"class":170}," 42",[131,621,622],{"class":145}," }\n",[131,624,625,627,629,631],{"class":133,"line":271},[131,626,17],{"class":137},[131,628,602],{"class":141},[131,630,588],{"class":145},[131,632,633],{"class":195},"\u002F\u002F 1   — primitive return ignored\n",[20,635,636,637,639,640,642,643,645],{},"This is why you almost never ",[15,638,570],{}," from a constructor. The object-override behavior is\noccasionally used for factory tricks, but in normal code it's a source of confusion — let\n",[15,641,17],{}," return ",[15,644,106],{}," implicitly.",[10,647,649,650,652],{"id":648},"the-forgotten-new-bug","The forgotten-",[15,651,17],{}," bug",[20,654,655,656,99,659,661,662,664,665,668],{},"The classic disaster: calling a constructor ",[31,657,658],{},"without",[15,660,17],{},". Without it, there's no new\nobject and ",[15,663,106],{}," is whatever the call site provides — ",[15,666,667],{},"undefined"," in strict mode, or the\nglobal object in sloppy mode. Either way, your \"instance\" is wrong.",[122,670,672],{"className":124,"code":671,"language":126,"meta":127,"style":127},"function User(name) { this.name = name }\n\nconst good = new User('Ada')   \u002F\u002F proper instance\nconst bad  = User('Grace')     \u002F\u002F in sloppy mode, sets global.name; returns undefined\nbad        \u002F\u002F undefined\n",[15,673,674,695,699,722,745],{"__ignoreMap":127},[131,675,676,678,681,683,685,687,689,691,693],{"class":133,"line":134},[131,677,138],{"class":137},[131,679,680],{"class":141}," User",[131,682,146],{"class":145},[131,684,294],{"class":149},[131,686,297],{"class":145},[131,688,106],{"class":170},[131,690,302],{"class":145},[131,692,305],{"class":137},[131,694,308],{"class":145},[131,696,697],{"class":133,"line":164},[131,698,281],{"emptyLinePlaceholder":280},[131,700,701,703,706,708,710,712,714,717,719],{"class":133,"line":199},[131,702,447],{"class":137},[131,704,705],{"class":170}," good",[131,707,174],{"class":137},[131,709,455],{"class":137},[131,711,680],{"class":141},[131,713,146],{"class":145},[131,715,716],{"class":239},"'Ada'",[131,718,192],{"class":145},[131,720,721],{"class":195},"\u002F\u002F proper instance\n",[131,723,724,726,729,732,734,736,739,742],{"class":133,"line":221},[131,725,447],{"class":137},[131,727,728],{"class":170}," bad",[131,730,731],{"class":137},"  =",[131,733,680],{"class":141},[131,735,146],{"class":145},[131,737,738],{"class":239},"'Grace'",[131,740,741],{"class":145},")     ",[131,743,744],{"class":195},"\u002F\u002F in sloppy mode, sets global.name; returns undefined\n",[131,746,747,750],{"class":133,"line":271},[131,748,749],{"class":145},"bad        ",[131,751,752],{"class":195},"\u002F\u002F undefined\n",[20,754,755,756,759,760,762,763,766,767,93],{},"In sloppy mode this silently pollutes the global object; in strict mode (and inside ES\nmodules, which are always strict) it throws ",[15,757,758],{},"TypeError: Cannot set property 'name' of undefined",", which at least fails loudly. This bug is exactly why ",[15,761,37],{}," constructors\n",[46,764,765],{},"throw"," if you call them without ",[15,768,17],{},[10,770,772,773],{"id":771},"guarding-against-missing-new","Guarding against missing ",[15,774,17],{},[20,776,777,778,780,781,784,785,787],{},"Before ",[15,779,37],{},", defensive constructors guarded themselves with ",[15,782,783],{},"new.target"," or an\n",[15,786,335],{}," check:",[122,789,791],{"className":124,"code":790,"language":126,"meta":127,"style":127},"function User(name) {\n  if (!(this instanceof User)) return new User(name)  \u002F\u002F auto-correct\n  this.name = name\n}\nUser('Ada').name   \u002F\u002F 'Ada' — works with or without new\n",[15,792,793,805,839,850,854],{"__ignoreMap":127},[131,794,795,797,799,801,803],{"class":133,"line":134},[131,796,138],{"class":137},[131,798,680],{"class":141},[131,800,146],{"class":145},[131,802,294],{"class":149},[131,804,161],{"class":145},[131,806,807,810,812,815,817,819,822,824,827,829,831,833,836],{"class":133,"line":164},[131,808,809],{"class":137},"  if",[131,811,227],{"class":145},[131,813,814],{"class":137},"!",[131,816,146],{"class":145},[131,818,106],{"class":170},[131,820,821],{"class":137}," instanceof",[131,823,680],{"class":141},[131,825,826],{"class":145},")) ",[131,828,570],{"class":137},[131,830,455],{"class":137},[131,832,680],{"class":141},[131,834,835],{"class":145},"(name)  ",[131,837,838],{"class":195},"\u002F\u002F auto-correct\n",[131,840,841,843,845,847],{"class":133,"line":199},[131,842,370],{"class":170},[131,844,302],{"class":145},[131,846,305],{"class":137},[131,848,849],{"class":145}," name\n",[131,851,852],{"class":133,"line":221},[131,853,274],{"class":145},[131,855,856,859,861,863,866],{"class":133,"line":271},[131,857,858],{"class":141},"User",[131,860,146],{"class":145},[131,862,716],{"class":239},[131,864,865],{"class":145},").name   ",[131,867,868],{"class":195},"\u002F\u002F 'Ada' — works with or without new\n",[20,870,871,872,876,877,879,880,882],{},"A cleaner modern tool is ",[46,873,874],{},[15,875,783],{},", which is ",[15,878,667],{}," when a function is called\nwithout ",[15,881,17],{}," and the constructor reference when called with it.",[122,884,886],{"className":124,"code":885,"language":126,"meta":127,"style":127},"function Account(balance) {\n  if (new.target === undefined) {\n    throw new Error('Account must be called with new')   \u002F\u002F explicit guard\n  }\n  this.balance = balance\n}\n",[15,887,888,902,923,943,948,960],{"__ignoreMap":127},[131,889,890,892,895,897,900],{"class":133,"line":134},[131,891,138],{"class":137},[131,893,894],{"class":141}," Account",[131,896,146],{"class":145},[131,898,899],{"class":149},"balance",[131,901,161],{"class":145},[131,903,904,906,908,910,912,915,918,921],{"class":133,"line":164},[131,905,809],{"class":137},[131,907,227],{"class":145},[131,909,17],{"class":137},[131,911,93],{"class":145},[131,913,914],{"class":170},"target",[131,916,917],{"class":137}," ===",[131,919,920],{"class":170}," undefined",[131,922,161],{"class":145},[131,924,925,928,930,933,935,938,940],{"class":133,"line":199},[131,926,927],{"class":137},"    throw",[131,929,455],{"class":137},[131,931,932],{"class":141}," Error",[131,934,146],{"class":145},[131,936,937],{"class":239},"'Account must be called with new'",[131,939,192],{"class":145},[131,941,942],{"class":195},"\u002F\u002F explicit guard\n",[131,944,945],{"class":133,"line":221},[131,946,947],{"class":145},"  }\n",[131,949,950,952,955,957],{"class":133,"line":271},[131,951,370],{"class":170},[131,953,954],{"class":145},".balance ",[131,956,305],{"class":137},[131,958,959],{"class":145}," balance\n",[131,961,962],{"class":133,"line":277},[131,963,274],{"class":145},[10,965,967],{"id":966},"newtarget-and-abstract-constructors","new.target and abstract constructors",[20,969,970,972],{},[15,971,783],{}," also enables \"abstract\" base constructors that must be subclassed, not\ninstantiated directly.",[122,974,976],{"className":124,"code":975,"language":126,"meta":127,"style":127},"function Shape() {\n  if (new.target === Shape) {\n    throw new Error('Shape is abstract — extend it instead')\n  }\n}\nfunction Circle(r) { Shape.call(this); this.r = r }\nCircle.prototype = Object.create(Shape.prototype)\n\nnew Circle(5)   \u002F\u002F fine\nnew Shape()     \u002F\u002F Error: Shape is abstract\n",[15,977,978,988,1005,1020,1024,1028,1062,1087,1091,1106],{"__ignoreMap":127},[131,979,980,982,985],{"class":133,"line":134},[131,981,138],{"class":137},[131,983,984],{"class":141}," Shape",[131,986,987],{"class":145},"() {\n",[131,989,990,992,994,996,998,1000,1002],{"class":133,"line":164},[131,991,809],{"class":137},[131,993,227],{"class":145},[131,995,17],{"class":137},[131,997,93],{"class":145},[131,999,914],{"class":170},[131,1001,917],{"class":137},[131,1003,1004],{"class":145}," Shape) {\n",[131,1006,1007,1009,1011,1013,1015,1018],{"class":133,"line":199},[131,1008,927],{"class":137},[131,1010,455],{"class":137},[131,1012,932],{"class":141},[131,1014,146],{"class":145},[131,1016,1017],{"class":239},"'Shape is abstract — extend it instead'",[131,1019,465],{"class":145},[131,1021,1022],{"class":133,"line":221},[131,1023,947],{"class":145},[131,1025,1026],{"class":133,"line":271},[131,1027,274],{"class":145},[131,1029,1030,1032,1034,1036,1039,1042,1045,1047,1049,1052,1054,1057,1059],{"class":133,"line":277},[131,1031,138],{"class":137},[131,1033,358],{"class":141},[131,1035,146],{"class":145},[131,1037,1038],{"class":149},"r",[131,1040,1041],{"class":145},") { Shape.",[131,1043,1044],{"class":141},"call",[131,1046,146],{"class":145},[131,1048,106],{"class":170},[131,1050,1051],{"class":145},"); ",[131,1053,106],{"class":170},[131,1055,1056],{"class":145},".r ",[131,1058,305],{"class":137},[131,1060,1061],{"class":145}," r }\n",[131,1063,1064,1066,1068,1070,1072,1074,1076,1078,1081,1083,1085],{"class":133,"line":284},[131,1065,390],{"class":170},[131,1067,93],{"class":145},[131,1069,189],{"class":170},[131,1071,174],{"class":137},[131,1073,177],{"class":145},[131,1075,180],{"class":141},[131,1077,146],{"class":145},[131,1079,1080],{"class":170},"Shape",[131,1082,93],{"class":145},[131,1084,189],{"class":170},[131,1086,465],{"class":145},[131,1088,1089],{"class":133,"line":311},[131,1090,281],{"emptyLinePlaceholder":280},[131,1092,1093,1095,1097,1099,1101,1103],{"class":133,"line":468},[131,1094,17],{"class":137},[131,1096,358],{"class":141},[131,1098,146],{"class":145},[131,1100,462],{"class":170},[131,1102,192],{"class":145},[131,1104,1105],{"class":195},"\u002F\u002F fine\n",[131,1107,1108,1110,1112,1115],{"class":133,"line":482},[131,1109,17],{"class":137},[131,1111,984],{"class":141},[131,1113,1114],{"class":145},"()     ",[131,1116,1117],{"class":195},"\u002F\u002F Error: Shape is abstract\n",[20,1119,1120,1121,1123],{},"Inside a subclass call, ",[15,1122,783],{}," is the subclass, so the abstract check only fires when\nsomeone instantiates the base directly.",[10,1125,1127],{"id":1126},"the-constructor-property","The constructor property",[20,1129,1130,1131,1133,1134,1137],{},"Every function's ",[15,1132,189],{}," object has a ",[15,1135,1136],{},"constructor"," property pointing back to the\nfunction, so instances can discover what made them.",[122,1139,1141],{"className":124,"code":1140,"language":126,"meta":127,"style":127},"function Dog() {}\nconst d = new Dog()\nd.constructor === Dog          \u002F\u002F true\nd.constructor.name             \u002F\u002F 'Dog'\n",[15,1142,1143,1152,1168,1183],{"__ignoreMap":127},[131,1144,1145,1147,1149],{"class":133,"line":134},[131,1146,138],{"class":137},[131,1148,289],{"class":141},[131,1150,1151],{"class":145},"() {}\n",[131,1153,1154,1156,1159,1161,1163,1165],{"class":133,"line":164},[131,1155,447],{"class":137},[131,1157,1158],{"class":170}," d",[131,1160,174],{"class":137},[131,1162,455],{"class":137},[131,1164,289],{"class":141},[131,1166,1167],{"class":145},"()\n",[131,1169,1170,1173,1175,1177,1180],{"class":133,"line":199},[131,1171,1172],{"class":145},"d.",[131,1174,1136],{"class":170},[131,1176,917],{"class":137},[131,1178,1179],{"class":145}," Dog          ",[131,1181,1182],{"class":195},"\u002F\u002F true\n",[131,1184,1185,1187,1189,1192],{"class":133,"line":221},[131,1186,1172],{"class":145},[131,1188,1136],{"class":170},[131,1190,1191],{"class":145},".name             ",[131,1193,1194],{"class":195},"\u002F\u002F 'Dog'\n",[20,1196,1197,1198,1200,1201,1204,1205,93],{},"When you reassign ",[15,1199,92],{}," wholesale (common in manual inheritance), you wipe out this\nback-pointer and must restore it: ",[15,1202,1203],{},"Dog.prototype.constructor = Dog",". Forgetting to do so\nbreaks code that relies on ",[15,1206,1207],{},"instance.constructor",[10,1209,1211],{"id":1210},"constructors-vs-factory-functions","Constructors vs factory functions",[20,1213,1214,1215,1218,1219,1221,1222,1225,1226,1228,1229,1231],{},"You don't ",[31,1216,1217],{},"have"," to use ",[15,1220,17],{},". A ",[46,1223,1224],{},"factory function"," just builds and returns an object,\nsidestepping ",[15,1227,106],{}," and ",[15,1230,17],{}," entirely.",[122,1233,1235],{"className":124,"code":1234,"language":126,"meta":127,"style":127},"function createUser(name) {\n  return {\n    name,\n    greet() { return `Hi, ${name}` }   \u002F\u002F closure over name, no `this` needed\n  }\n}\nconst u = createUser('Ada')   \u002F\u002F no `new`, no this-binding pitfalls\n",[15,1236,1237,1250,1257,1262,1285,1289,1293],{"__ignoreMap":127},[131,1238,1239,1241,1244,1246,1248],{"class":133,"line":134},[131,1240,138],{"class":137},[131,1242,1243],{"class":141}," createUser",[131,1245,146],{"class":145},[131,1247,294],{"class":149},[131,1249,161],{"class":145},[131,1251,1252,1254],{"class":133,"line":164},[131,1253,224],{"class":137},[131,1255,1256],{"class":145}," {\n",[131,1258,1259],{"class":133,"line":199},[131,1260,1261],{"class":145},"    name,\n",[131,1263,1264,1267,1269,1271,1274,1276,1279,1282],{"class":133,"line":221},[131,1265,1266],{"class":141},"    greet",[131,1268,554],{"class":145},[131,1270,570],{"class":137},[131,1272,1273],{"class":239}," `Hi, ${",[131,1275,294],{"class":145},[131,1277,1278],{"class":239},"}`",[131,1280,1281],{"class":145}," }   ",[131,1283,1284],{"class":195},"\u002F\u002F closure over name, no `this` needed\n",[131,1286,1287],{"class":133,"line":271},[131,1288,947],{"class":145},[131,1290,1291],{"class":133,"line":277},[131,1292,274],{"class":145},[131,1294,1295,1297,1300,1302,1304,1306,1308,1310],{"class":133,"line":284},[131,1296,447],{"class":137},[131,1298,1299],{"class":170}," u",[131,1301,174],{"class":137},[131,1303,1243],{"class":141},[131,1305,146],{"class":145},[131,1307,716],{"class":239},[131,1309,192],{"class":145},[131,1311,1312],{"class":195},"\u002F\u002F no `new`, no this-binding pitfalls\n",[20,1314,1315,1316,1318,1319,1321,1322,1324],{},"Factories avoid the forgotten-",[15,1317,17],{}," bug and the confusion around ",[15,1320,106],{},", but each returned\nobject gets its own copy of every method (no shared prototype), which costs memory at scale.\nConstructors (and ",[15,1323,37],{},") trade a little ceremony for prototype-based method sharing.\nChoose factories for small counts and simplicity; constructors\u002Fclasses for many instances.",[10,1326,1328,1329,1331],{"id":1327},"how-class-relates","How ",[15,1330,37],{}," relates",[20,1333,1334,1335,1337,1338,1341,1342,1344,1345,1348,1349,1352,1353,1355],{},"The ",[15,1336,37],{}," keyword is sugar over everything above. ",[15,1339,1340],{},"class Dog {}"," creates a constructor\nfunction ",[15,1343,55],{},", puts its methods on ",[15,1346,1347],{},"Dog.prototype",", wires up ",[15,1350,1351],{},"extends"," via the same\nprototype linking, and adds the guard that throws when called without ",[15,1354,17],{},". There's no new\nruntime mechanism — just nicer syntax over constructors and prototypes.",[10,1357,1359],{"id":1358},"key-takeaways","Key takeaways",[1361,1362,1363,1378,1386,1392,1406,1414],"ul",{},[78,1364,1365,1368,1369,1371,1372,1374,1375,1377],{},[15,1366,1367],{},"new Fn()"," does four things: create an object, link it to ",[15,1370,92],{},", call ",[15,1373,102],{}," with\n",[15,1376,106],{}," bound to it, and return it (unless the constructor returns its own object).",[78,1379,1380,1381,1383,1384,93],{},"Initialize instance state on ",[15,1382,106],{},"; put shared methods on ",[15,1385,92],{},[78,1387,1388,1389,1391],{},"A constructor returning an ",[46,1390,531],{}," overrides the new instance; returning a primitive is\nignored.",[78,1393,1394,1395,1397,1398,1400,1401,1403,1404,93],{},"Calling a constructor without ",[15,1396,17],{}," is a classic bug — ",[15,1399,667],{},"\u002Fglobal ",[15,1402,106],{},"; guard\nwith ",[15,1405,783],{},[78,1407,1408,1410,1411,1413],{},[15,1409,783],{}," distinguishes ",[15,1412,17],{}," calls and enables abstract base constructors.",[78,1415,1416,1417,1419,1420,1422,1423,1425],{},"Factory functions avoid ",[15,1418,106],{},"\u002F",[15,1421,17],{}," entirely at the cost of per-instance methods; ",[15,1424,37],{},"\nis just sugar over constructors and prototypes.",[20,1427,1428,1429,1431],{},"Understanding ",[15,1430,17],{}," turns constructors and classes from incantations into a clear,\nfour-step process you could implement yourself — which is exactly the level of understanding\nthat separates confident JavaScript developers from the rest.",[1433,1434,1435],"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 pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}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);}",{"title":127,"searchDepth":164,"depth":164,"links":1437},[1438,1440,1442,1443,1444,1446,1448,1449,1450,1451,1453],{"id":12,"depth":164,"text":1439},"What new really does",{"id":63,"depth":164,"text":1441},"The four steps of new",{"id":339,"depth":164,"text":340},{"id":524,"depth":164,"text":525},{"id":648,"depth":164,"text":1445},"The forgotten-new bug",{"id":771,"depth":164,"text":1447},"Guarding against missing new",{"id":966,"depth":164,"text":967},{"id":1126,"depth":164,"text":1127},{"id":1210,"depth":164,"text":1211},{"id":1327,"depth":164,"text":1452},"How class relates",{"id":1358,"depth":164,"text":1359},"A deep dive into JavaScript's new operator and constructor functions — what new actually does step by step, return values, new.target, and the classic forgotten-new bug.","medium","md","JavaScript","javascript",{},"\u002Fblog\u002Fjavascript-new-operator-constructor-functions","\u002Fjavascript\u002Fobjects\u002Fnew-constructors",{"title":5,"description":1454},"blog\u002Fjavascript-new-operator-constructor-functions","The new Operator & Constructors","Objects & Prototypes","objects","2026-06-18","pnApSU7MgfFt6TXrZcCPsrdtvFbbL36RkeZaZsE2gS0",1781808673080]