Constructor in Strict Mode [closed] - javascript

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 months ago.
Improve this question
I've been searching a lot for an answer to this REALLY simple question, but I cannot find it:
" How to create constructors in strict mode ? "
fetch(`https://restcountries.com/v3.1/name/${country_name}`, )
.then(response => {
if(! response.ok)
throw new MyError(response.statusText, response.status)
[...]
.catch(err => {
renderNotFound(err.message, err.code)
[...]
class MyError {
constructor(message, code) {
this.message = message
this.code = code
}}
I know the .this keyword resolves to undefined in strict node. So how can we work around it to create constructors?
Thanks in advance
EDIT: fixed a missing } in the class MyError

How to create constructors in strict mode?
When using class syntax, constructor functions are always in strict mode, because the body of a class is always strict. (Most new kinds of scope defined in ES2015+ are strict by default.)
I know the .this keyword resolves to undefined in strict node. So how can we work around it to create constructors?
No workaround required. this is set to undefined when you call a function without doing anything to set this (for example: example()). When you use new, this is set to an instance of the thing being created before your constructor code is called (in a base constructor) or when you call super(/*...*/) (in a subclass constructor). (And when you do something else to set this (like example.method() or method.call(example)), this is set just like it is in loose mode.) Example:
class MyError {
constructor(message, code) {
this.message = message
this.code = code
}
}
const x = new MyError("Ooops!", 42);
console.log(x.message); // Ooops!
console.log(x.code); // 42
Just to underscore the point that class bodies are in strict mode by default:
class MyError {
// Code here is strict, even though the script
// context around it isn't
static example() {
console.log(this === undefined);
}
}
const loose = {
// Code here is loose like the script context around it
example() {
console.log(this === undefined);
}
};
let f;
f = MyError.example;
f(); // true
f = loose.example;
f(); // false
In a comment you've suggested that code doesn't work in strict mode. It should, assuming you have a } on your class. It does in this fiddle (can't do fetch in stack snippets, sadly):
"use strict";
class MyError {
constructor(message, code) {
this.message = message
this.code = code
}
}
fetch(`/this-will-404`, )
.then(response => {
if(! response.ok)
throw new MyError(response.statusText, response.status)
})
.catch(err => {
renderNotFound(err.message, err.code);
});
function renderNotFound(message, code) {
console.log(`Not found: ${message} ${code}`);
}

Related

How to use global object window or document in javascript es6 Class [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
How can I use the window or document inside a JavaScript ES6 class
I tried the following code
Scenario #1:
class App {
constructor() {
console.info('App Initialized');
document.addEventListener('DOMContentLoaded', function() {
console.info('document Initialized');
this.initializeView();
}).bind(this);
}
initializeView() {
console.info('View Initialized');
}
}
const app = new App();
Note: I compiled the above code using gulp js
If I tried to call the class method inside the document.addEventListener, it throws the following error.
Uncaught TypeError: this.initializeView is not a function
So, I binded the this object to document .bind(this)
Scenario #2:
class App {
constructor() {
console.info('App Initialized');
document.addEventListener('DOMContentLoaded', function() {
console.info('document Initialized');
}).bind(this);
}
}
const app = new App();
If I tried without document.addEventListener, its working as expected in browser but if I tried with the document.addEventListener it throws an error
Uncaught TypeError: document.addEventListener(...) is undefined
Please assist me how to use the window or document inside the es6 class.
Scenarion #3:
class Booking {
stepper = 1;
constructor() {
console.info('Booking Initialized');
document.addEventListener('DOMContentLoaded', function() {
console.log('document Initialized')
});
}
}
I'm getting the following exception
Uncaught ReferenceError: options is not defined
The referred solution is not has any relevance to the Question's
subject matter
How to access the correct `this` inside a callback
I'm not sure how the expertise people giving the above link as a
solution.
You don't want to use a function(){} for your event handling, because regular functions derive this from the context at runtime, and that context is not your object, but the global context. Using the ancient bind() function (if done right) gets around that, but so does modern arrow function syntax, so use that instead.
constructor() {
console.info('App Initialized');
document.addEventListener('DOMContentLoaded', () => {
console.info('document Initialized');
this.initializeView();
});
}
Done.
However, this is silly code and we don't have to do this at all: load your script in the <head> element, as <script src="..." async defer></script>, using the defer attribute so that your script doesn't run until the DOM is ready for queries. It's been around for about a decade now, no need for that event listening; just run the code that needs to run.
constructor() {
console.info('App Initialized');
this.initializeView();
}

How can I find where my object is being frozen?

I get this error:
Error: You attempted to set the key `TpDeF3wd6UoQ6BjEFmwz` with the value `{"seen":true}` on an object that is meant to be immutable and has been frozen.
How can I discover what code is directly/indirectly freezing my object and making it immutable?
I've solved the error in development by rewriting the logic completely, but I'd like to understand how to debug this type of error.
One idea it to replace Object.freeze with your own that logs the stack, and then calls the old freeze.
Below is an example, you can see it's at 30:8
The line numbers in this snippet don't line up, only because SO snippets will be adding some extra wrapper code, but in production this should give you the correct line no.
'use strict';
function DebugFreeze() {
const oldFree = Object.freeze;
Object.freeze = (...args) => {
console.log(new Error("Object Frozen").stack);
return oldFree.call(Object, ...args);
}
}
DebugFreeze();
const a = { one: 1 };
a.two = 2;
Object.freeze(a);
a.three = 3;
console.log("here");

How to avoid accidentally implicitly referring to properties on the global object?

Is it possible to execute a block of code without the implicit with(global) context that all scripts seem to have by default? For example, in a browser, would there be any way to set up a script so that a line such as
const foo = location;
throws
Uncaught ReferenceError: location is not defined
instead of accessing window.location, when location has not been declared first? Lacking that, is there a way that such an implicit reference could result in a warning of some sort? It can be a source of bugs when writing code (see below), so having a way to guard against it could be useful.
(Of course, due to ordinary scoping rules, it's possible to declare another variable with the same name using const or let, or within an inner block, to ensure that using that variable name references the new variable rather than the global property, but that's not the same thing.)
This may be similar to asking whether it's possible to stop referencing a property from within an actual with statement:
const obj = { prop: 'prop' };
with (obj) {
// how to make referencing "prop" from somewhere within this block throw a ReferenceError
}
It's known that with should not be used in the first place, but unfortunately it seems we have no choice when it comes to the with(global), which occasionally saves a few characters at the expense of confusing bugs which pop up somewhat frequently: 1 2 3 4 5 6. For example:
var status = false;
if (status) {
console.log('status is actually truthy!');
}
(the issue here: window.status is a reserved property - when assigned to, it coerces the assigned expression to a string)
These sorts of bugs are the same reason that explicit use of with is discouraged or prohibited, yet the implicit with(global) continues to cause issues, even in strict mode, so figuring out a way around it would be useful.
There are some things you need to consider before trying to answer this question.
For example, take the Object constructor. It is a "Standard built-in object".
window.status is part of the Window interface.
Obviously, you don't want status to refer to window.status, but do you want Object to refer to window.Object?
The solution to your problem of it not being able to be redefined is to use a IIFE, or a module, which should be what you are doing anyways.
(() => {
var status = false;
if (!status) {
console.log('status is now false.');
}
})();
And to prevent accidentally using global variables, I would just set up your linter to warn against it. Forcing it using a solution like with (fake_global) would not only have errors exclusively at run time, which might be not caught, but also be slower.
Specifically with ESLint, I can't seem to find a "good" solution. Enabling browser globals allows implicit reads.
I would suggest no-implicit-globals (As you shouldn't be polluting the global scope anyways, and it prevents the var status not defining anything problem), and also not enabling all browser globals, only, say, window, document, console, setInterval, etc., like you said in the comments.
Look at the ESLint environments to see which ones you would like to enable. By default, things like Object and Array are in the global scope, but things like those listed above and atob are not.
To see the exact list of globals, they are defined by this file in ESLint and the globals NPM package. I would would pick from (a combination of) "es6", "worker" or "shared-node-browser".
The eslintrc file would have:
{
"rules": {
"no-implicit-globals": "error"
},
"globals": {
"window": "readonly",
"document": "readonly"
},
"env": {
"browser": false,
"es6": [true/false],
"worker": [true/false],
"shared-node-browser": [true/false]
}
}
If you're not in strict mode, one possibility is to iterate over the property names of the global (or withed) object, and create another object from those properties, whose setters and getters all throw ReferenceErrors, and then nest your code in another with over that object. See comments in the code below.
This isn't a nice solution, but it's the only one I can think of:
const makeObjWhosePropsThrow = inputObj => Object.getOwnPropertyNames(inputObj)
.reduce((a, propName) => {
const doThrow = () => { throw new ReferenceError(propName + ' is not defined!'); };
Object.defineProperty(a, propName, { get: doThrow, set: doThrow });
return a;
}, {});
// (using setTimeout so that console shows both this and the next error)
setTimeout(() => {
const windowWhichThrows = makeObjWhosePropsThrow(window);
with (windowWhichThrows) {
/* Use an IIFE
* so that variables with the same name declared with "var" inside
* create a locally scoped variable
* rather than try to reference the property, which would throw
*/
(() => {
// Declaring any variable name will not throw:
var alert = true; // window.alert
const open = true; // window.open
// Referencing a property name without declaring it first will throw:
const foo = location;
})();
}
});
const obj = { prop1: 'prop1' };
with (obj) {
const inner = makeObjWhosePropsThrow(obj);
with (inner) {
// Referencing a property name without declaring it first will throw:
console.log(prop1);
}
}
.as-console-wrapper {
max-height: 100% !important;
}
Caveats:
This explicitly uses with, which is forbidden in strict mode
This doesn't exactly escape the implicit with(global) scope, or the with(obj) scope: variables in the outer scope with the same name as a property will not be referenceable.
window has a property window, which refers to window. window.window === window. So, referencing window inside the with will throw. Either explicitly exclude the window property, or save another reference to window first.
Somewhat simpler to implement than #CertainPerformance's answer, you can use a Proxy to catch implicit access to everything except window. The only caveat is you can't run this in strict mode:
const strictWindow = Object.create(
new Proxy(window, {
get (target, property) {
if (typeof property !== 'string') return undefined
console.log(`implicit access to ${property}`)
throw new ReferenceError(`${property} is not defined`)
}
}),
Object.getOwnPropertyDescriptors({ window })
)
with (strictWindow) {
try {
const foo = location
} catch (error) {
window.console.log(error.toString())
}
// doesn't throw error
const foo = window.location
}
Notice that even console has to have an explicit reference in order to not throw. If you want to add that as another exception, just modify strictWindow with another own property using
Object.getOwnPropertyDescriptors({ window, console })
In fact, there are a lot of standard built-in objects you may want to add exceptions for, but that is beyond the scope of this answer (no pun intended).
In my opinion, the benefits this offers fall short of the benefits of running in strict mode. A much better solution is to use a properly configured linter that catches implicit references during development rather than at runtime in non-strict mode.
Perhaps slightly cleaner (YMMV) is to set getter traps (like you did), but in a worker so that you don't pollute your main global scope. I didn't need to use with though, so perhaps that is an improvement.
Worker "Thread"
//worker; foo.js
addEventListener('message', function ({ data }) {
try {
eval(`
for (k in self) {
Object.defineProperty(self, k, {
get: function () {
throw new ReferenceError(':(');
}
});
}
// code to execute
${data}
`);
postMessage('no error thrown ');
} catch (e) {
postMessage(`error thrown: ${e.message}`);
}
});
Main "Thread"
var w = new Worker('./foo.js');
w.addEventListener('message', ({data}) => console.log(`response: ${data}`));
w.postMessage('const foo = location');
Another option that may be worth exploring is Puppeteer.
Just use "use strict". More on Strict Mode.

How to protect functions which are called with different contexts from breaking?

I'm fairly new to javascript and now I learned how calling functions with a context works.
Here is a simple example that poses a question in my head. Lets say we have this example:
var myObj = {
bar: function() {
console.log("Lets got to the bar!");
}
}
/* how can this be protected from errors,
* if a passed object doesn't contain bar */
function foo()
{
this.bar();
}
foo.call(myObj);
Now, how can foo be protected of breaking? In some OOP language (lets say Java) this would be implemented lets say via an interface. So in that case if the object being instantiated hasn't implemented the interface method, the compiler would through an error so the compiler protects the code/program from being faulty (in this case of course).
public interface MyInterface
{
public void bar();
}
public class MyClass implements MyInterface
{
public void bar()
{
System.println("Lets go to the bar");
}
}
MyInterface m = new MyClass();
m.bar(); // if bar isn't implemented the compiler would warn/break
Note: I'm not that good in Java so sorry for any syntax or other errors, but I hope you get the point.
So to sum up, as I see that in both cases in both languages one can achieve polymorphism, right? Now if so for the Javascript example, how can one protect it from breaking, are there any patterns or tricks? Does typeof this.bar === function work? If so, who guarantees the SW quality if the programmer forgets this, I'm asking this kind of question because Java has the compiler to warn the programmer about the mistake, does JS have something similar, some quality check tool?
Javascript is a dynamic interpeted* language. There isn't a compiler step to check references. Some tools (jsline) and IDEs (VS, Webstorm) can perform some design-time checks for you, but there's no true type safety. This is largely seen as a feature, not a bug.
There's an array of tricks to work around this (.hasOwnProperty, typeof x === 'function', storing self references, context binding) but mostly, if you want a type safety, you want a different language.
My recommendation is Typescript. It has a Java/C-like syntax, with some familiar OOP features, like classes, interface (and thus, sane polymorphism) and generic types, and transpiles to javascript in moments.
If you use a constructor to create your object you can use Javascript's builtin class member ship checking features. An example is below.
class MyClass {
bar() { console.log("Lets got to the bar!")}
}
function foo() {
if ( this instanceof MyClass ) {
this.bar();
}
else {
console.log('this is not a member of the MyClass');
}
}
foo.call(new MyClass);
Be warned that Javascript's type checking is horribly unreliable and you probably should not use it. If your object contains the same prototype anywhere in it's prototype chain as the class you are testing it for membership in, instanceof will return true.
Quick and dirty duck typing example
This will throw if you give it an object without the properties you are checking for, but you get the idea.
class MyClass {
constructor() {
this.feathers = 'white';
this.feet = 'webbed';
}
bar() { console.log("Lets got to the bar!")}
}
function foo() {
if (
this.hasOwnProperty('feathers') &&
this.hasOwnProperty('feet') &&
this.feathers === 'white' &&
this.feet === 'webbed'
)
{
this.bar();
}
else {
console.log('this is not a member of the MyClass');
}
}
foo.call(new MyClass);

Howto: reference a library in JSLint

I'm using JSLint to do code review/cleanup on a massive series of scripts that interact with an external ERP system.
The problem I am having is that JSLint complains that the methods in the API are used before they are defined.
How can I reference a library within JSLint so that proper lookups are done? I have 493 functions I need to reference so /*Global*/ is not an option.
If this is not possible, is there a better way to do this?
I referenced this post which is asking for something similar, however the answer requires a restructure of the API which is not possible for me to do.
What's the library? Usually, you hope a library has everything namespaced properly so it's not an issue, as in /*global $*/ for jQuery. If the lib is internal and you can edit it, consider doing so (if you want to stick with strict JSLint compliance).
So...
function myFunc1(param1) {
return param1 + "some string1";
}
function myFunc2(param2) {
return param2 + "some string2";
}
becomes...
var fauxNamespace = {
myFunc1: function (param1) {
return param1 + "some string1";
},
myFunc2: function (param2) {
return param2 + "some string2";
}
};
Then you can /*global fauxNamespace*/ and profit. I realize that's non-trivial, but it's The Right Thing to Do (c) Crockford 2008.
Otherwise you're back to the normal "Use JSHint. It's happier because more options," or "JSLint has very clean code. You can actually hack it up yourself to ignore that error if you want," sorts of answers.
What you're looking for is currently on around line 2459:
// If the master is not in scope, then we may have an undeclared variable.
// Check the predefined list. If it was predefined, create the global
// variable.
if (!master) {
writeable = predefined[name];
if (typeof writeable === 'boolean') {
global_scope[name] = master = {
dead: false,
function: global_funct,
kind: 'var',
string: name,
writeable: writeable
};
// But if the variable is not in scope, and is not predefined, and if we are not
// in the global scope, then we have an undefined variable error.
} else {
token.warn('used_before_a');
}
} else {
this.master = master;
}
Is the library public?

Categories

Resources