What Is "New.Target"

What is new.target ?

You didn't find it in the spec because in the syntax definitions it is written with blanks, as new . target. The name of the expression is NewTarget, and you'll find that term a few times around.

NewTarget is the first of the so-called meta properties and can be found in §12.3.8.

Its sole purpose is to retrieve the current value of the [[NewTarget]] value of the current (non-arrow) function environment. It is a value that is set when a function is called (very much like the this binding), and according to §8.1.1.3 Function Environment Records:

If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.

So, for one thing, finally enables us to detect whether a function was called as a constructor or not.

But that's not its real purpose. So what is it then? It is part of the way how ES6 classes are not only syntactic sugar, and how they allow us inheriting from builtin objects. When you call a class constructor via new X, the this value is not yet initialised - the object is not yet created when the constructor body is entered. It does get created by the super constructor during the super() call (which is necessary when internal slots are supposed to be created). Still, the instance should inherit from the .prototype of the originally called constructor, and that's where newTarget comes into the play. It does hold the "outermost" constructor that received the new call during super() invocations. You can follow it all the way down in the spec, but basically it always is the newTarget not the currently executed constructor that does get passed into the OrdinaryCreateFromConstructor procedure - for example in step 5 of §9.2.2 [[Construct]] for user-defined functions.

Long text, maybe an example is better suited:

class Parent {
constructor() {
// implicit (from the `super` call)
// new.target = Child;
// implicit (because `Parent` doesn't extend anything):
// this = Object.create(new.target.prototype);
console.log(new.target) // Child!
}
}
class Child extends Parent {
constructor() {
// `this` is uninitialised (and would throw if accessed)
// implicit (from the `new` call):
// new.target = Child
super(); // this = Reflect.construct(Parent, [], new.target);
console.log(this);
}
}
new Child;

JS new.target vs. instanceof

Using this instanceof Foo you will check if this instance is a Foo, but you can't ensure that was called with a new.
I can just do a thing like this

var foo = new Foo("Test");
var notAFoo = Foo.call(foo, "AnotherWord");

And will work fine. Using new.target you can avoid this issues.
I suggest you to read this book https://leanpub.com/understandinges6/read

What is javascript Reflect.construct newTarget doing

I'd say the documentation is somewhat misleadingly worded. What seems to be happening is that construct() invokes the first the first argument as the constructor (i.e. to initialize the object), but uses the last argument as the prototype (i.e. the actual "class" of the object). In your case, result instanceof Child returns true, but result instanceof Parent returns false.

So, the result of Reflect.construct(target, args, newTarget) seems to be equivalent to this:

var result = Object.create(newTarget.prototype);
target.apply(result, args);

However, there is one significant difference: in the above example, the new.target operator within either function will return undefined, since you're not using the new keyword to create the object. When you use Reflect.construct(), on the other hand, new.target will point to newTarget (hence the name, I suppose) -- probably because, in the end, the resulting object will belong to that class.

(Note: I have since requested an edit to the MDN page about Reflect.construct() to include these details)

new.target property behaves unexpected in bound functions

new.target does not always refer to the called function. Rather, it refers to the function whose .prototype property should be used as the prototype for the new instance (so that superclasses can create the right thing).

The .bind() method does create special "bound function" objects whose only purpose it is to call the original function with the provided this value and partially applied arguments list. They don't even have a .prototype property - which should make clear that they are not an appropriate value for new.target. And indeed, their [[construct]] method is specified to use the original function in place of the bound function.


So what should you do here? Of course, "using new to configure functions" should be avoided in production code, but it's a nice experiment. I would suggest to avoid bind here and instead make use of closures:

function makeTest(config) {
return function ConfiguredTest(newConfig) {
if (new.target) {
let mergedConfig = {};
Object.assign(mergedConfig, newConfig || {}, config) // I presume you want to swap the latter two
return makeTest(mergedConfig);
} else {
// use `config` here
return config.a + config.b;
}
};
}
const Test = makeTest({});

// like before
let Test2 = new Test(…)
let Test3 = new Test2(…)
Test3()

new.target with a prefix operator

This syntax should be supported, and the error was confirmed to be a webkit bug:

if(!new.target){
throw new Error('Must be called with new keyword!')
}

A patch has been written and merged, and will ship with a future version of webkit

https://bugs.webkit.org/show_bug.cgi?id=157970#c17

Until the fix lands in a released version, a workaround is to explicitly check new.target

if(new.target === undefined){
throw new Error('Must be called with new keyword!')
}

How do you polyfill Javascript ES6 `new.target`?

As Jaromanda commented, you cannot polyfill new syntax, but you can easily work around some new.target use cases for now

Taking a look at the new.target docs you'll see some examples that can easily be written with es5

with new.target

function Foo() {
if (!new.target) throw "Foo() must be called with new";
console.log("Foo instantiated with new");
}

Foo(); // throws "Foo() must be called with new"
new Foo(); // logs "Foo instantiated with new"

without

function Foo() {
if (!(this instanceof Foo)) throw "Foo() must be called with new";
console.log("Foo instantiated with new");
}

Foo(); // throws "Foo() must be called with new"
new Foo(); // logs "Foo instantiated with new"

with new.target

class A {
constructor() {
console.log(new.target.name);
}
}

class B extends A { constructor() { super(); } }

var a = new A(); // logs "A"
var b = new B(); // logs "B"

without

class A {
constructor() {
// class forces constructor to be called with `new`, so
// `this` will always be set
console.log(this.constructor.name);
}
}

class B extends A { constructor() { super(); } }

var a = new A(); // logs "A"
var b = new B(); // logs "B"

Hope this helps a little

target= _blank vs. target= _new

Use "_blank"

According to the HTML5 Spec:

A valid browsing context name is any string with at least one character that does not start with a U+005F LOW LINE character. (Names starting with an underscore are reserved for special keywords.)

A valid browsing context name or keyword is any string that is either a valid browsing context name or that is an ASCII case-insensitive match for one of: _blank, _self, _parent, or _top." - Source

That means that there is no such keyword as _new in HTML5, and not in HTML4 (and consequently XHTML) either. That means, that there will be no consistent behavior whatsoever if you use this as a value for the target attribute.

Security recommendation

As Daniel and Michael have pointed out in the comments, when using target _blank pointing to an untrusted website, you should, in addition, set rel="noopener". This prevents the opening site to mess with the opener via JavaScript. See this post for more information.

New target column based on a pattern

First create a dict for mapping the target, then apply it to every target

m = dict((zip(df.source, df.target)))
def mapper(x):
for i in range(len(m)):
x = m.get(x, x)
return x

df["new_target"] = df.target.apply(mapper)

How to target the selector on new tab after clicking a[target= _blank ] - Failing to activate the new tab created

managed to solve this together (Linker :)

Process

First, we mapped the target being created to check for focus

browser.on('targetcreated', function (target) {
console.log('New tab:');
console.log(target);
});

We saw the URL is trying to open - for some reason the URLs in the target were empty. We re-installed stuff to rule out weird dependency bugs, then figured there's a focus issue.

Workaround

To solve it, we need to wait for the .newPage() to open before goto'ing to the URL, calling bringToFront() and then waiting for it to load (short sleep is the easy way). Once we did that, we had a working POC to start from.

Relevant part from the solution:

let mappedURL = tabs
.map((e, index) => e.url())
.filter((e, idx) => idx == 2)
console.log("MAPPED URL ", mappedURL)
sleep(2500)
const page3 = await browser.newPage()
await page3.goto(`${mappedURL}`)
await page3.bringToFront()

Ref

Here's a cool SO Answer showing how to use once syntax to test the event. Happy we were able to solve it, and I hope the process helps other people out.



Related Topics



Leave a reply



Submit