What's the purpose of Object(this) in javascript? - javascript

Studying the polyfill for the find method written on the MDN web docs, there's a particular line that I'm not following, let me share the code
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
if (this == null) {
throw TypeError('"this" is null or not defined');
}
var o = Object(this);
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
k++;
}
return undefined;
},
configurable: true,
writable: true
});
}
My question is with the expression var o = Object(this);. What's the purpose of doing so instead of doing var o = this?. Printing the value in both described cases returns the same object.
Is this an abbreviated way of calling var o = new Object(this);?
I have removed the comments from the method to shorten the text, here's the link to the polyfill implementation.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill
Thanks!

In strict mode, this isn't always an object. Object(this) makes sure that o is an object, not a primitive.
Here's an example of this being a primitive:
"use strict";
Object.defineProperty(String.prototype, "nishCap", {
writable: true,
configurable: true,
value() {
console.log(typeof this); // "string"
const o = Object(this);
console.log(typeof o); // "object"
return o.substring(0,1).toUpperCase() + o.substring(1);
}
});
const capped = "foo".nishCap();
Note that this even applies to array methods, because you can call them on non-arrays, like Array.prototype.find.call("foo", ch => ch === "o").
Is this an abbreviated way of calling var o = new Object(this);?
No, new Object always creates a new object (and doesn't use the argument you give it). When you call Object as a function, it coerces its argument to object. So a primitive string becomes a String object, a primitive number becomes a Number object, etc.
What's the purpose of doing so instead of doing var o = this?
That polyfill is fairly closely following the spec, which starts out with:
Let O be ? ToObject(this value).
In most cases it wouldn't be important, but I wouldn't be surprised if there were some edge case where leaving it out would cause observable behavior at variance with the spec.

Because Array.prototype.find can be called with a this value which is not an object. See the specification:
When the find method is called, the following steps are taken:
Let O be ? ToObject(this value).
So, in order to be perfectly compliant with the specification, the polyfill needs Object(this). Otherwise, the implementations will not be the same, as you can see by the following two snippets:
'use strict';
const str = 'abc';
Array.prototype.find.call(
str,
(char, i, theThis) => {
// theThis should be an object, even if called on a non-object:
console.log(theThis);
}
);
'use strict';
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
if (this == null) {
throw TypeError('"this" is null or not defined');
}
// Without object wrapping:
var o = this; // <-------------------------------
var len = o.length >>> 0;
if (typeof predicate !== 'function') {
throw TypeError('predicate must be a function');
}
var thisArg = arguments[1];
var k = 0;
while (k < len) {
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
k++;
}
return undefined;
},
configurable: true,
writable: true
});
const str = 'abc';
Array.prototype.find.call(
str,
(char, i, theThis) => {
// The polyfill above had no object wrapping, so this result is not the same:
console.log(theThis);
}
);

Related

Confused about polyfill of Array.prototype.reduce [duplicate]

This question already has answers here:
Why checking null in Array.prototype.forEach()?
(1 answer)
Object() without the new keyword or .create method
(1 answer)
Array Reduce Polyfill Explanation
(2 answers)
JavaScript 'in' operator for `undefined` elements in Arrays
(3 answers)
Closed 4 years ago.
This code is polyfill of Array.prototype.reduce given on Mozilla Developer Network.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback /*, thisArg*/) {
var T, A, k
if (this == null) {
throw new TypeError('this is null or not defined')
}
var O = Object(this)
var len = O.length >>> 0
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function')
}
if (arguments.length > 1) {
T = arguments[1]
}
A = new Array(len)
k = 0
while (k < len) {
var kValue, mappedValue
if (k in O) {
kValue = O[k]
mappedValue = callback.call(T, kValue, k, O)
A[k] = mappedValue
}
k++
}
return A
}
}
What I don't understand is these two lines
1.Why not just use this?
var O = Object(this)
2.Is it possible this be null, why need this code below?
if (this == null) {
throw new TypeError('this is null or not defined')
}
3.Why we need k in O? while k < len, k always in O, is it useless condition?
if (k in O) {
kValue = O[k]
mappedValue = callback.call(T, kValue, k, O)
A[k] = mappedValue
}
1.Why not just use this?
var O = Object(this)
In Edition 3, an undefined or null thisArg is replaced with the global object and ToObject is applied to all other values and that result is passed as the this value.
So my guess is that the reasons this is being done is to keep consistency.
2.Is it possible this be null, why need this code below?
if (this == null) {
throw new TypeError('this is null or not defined')
}
Yes, it is possible for this to be null.
Execute the following code with and without strict mode. You will notice that in strict mode the output is null, while in the other case its the window.
// "use strict";
var x = function(){
console.log(this);
return this;
}
x.call(null);
3.Why we need k in O? while k < len, k always in O, is it useless condition?
if (k in O) {
kValue = O[k]
mappedValue = callback.call(T, kValue, k, O)
A[k] = mappedValue
}
Not a useless condition, because it checks if a property exists.(see in operator examples)
Adding an example with sparse arrays:
var a = new Array(3);
console.log(a); // [ , , ]
console.log(a.length); // 3
console.log(a[0]); // undefined

Iterate through ALL values in a collection before returning true or false

I was wondering if there's more "functional" way to do this. Meaning, rather than having to do something like this:
let flag = true;
[1, 2, 3].forEach(n => if (n > 2) flag = false);
return flag;
I'm looking for something closer to this:
return [1, 2, 3].overEvery(n => n > 2);
The closest solution I've found is the Array.prototype.every function, but it terminates once it returns false, without iterating through the rest of the values in the collection.
Reason why I don't want to terminate is because I want to iterate through ALL fields in a form to display all the form errors before returning true or false in the form's onsubmit handler.
You can use Array.filter, which will return the elements that failed the validation if you return true for the elements that should fail.
Here is another approach:
function a()
{
var flag = true;
[1, 2, 3].forEach(function(value) { if(value > 2) flag = false; });
return flag;
}
console.log(a());
You can do a new prototype function that is like every but checks all the records:
if (!Array.prototype.everyCheckAll) {
Array.prototype.everyCheckAll = function(callbackfn, thisArg) {
'use strict';
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the this
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method
// of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callbackfn) is false, throw a TypeError exception.
if (typeof callbackfn !== 'function') {
throw new TypeError();
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let k be 0.
k = 0;
// 7. Repeat, while k < len
var oneFalse = false;
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method
// of O with argument Pk.
kValue = O[k];
// ii. Let testResult be the result of calling the Call internal method
// of callbackfn with T as the this value and argument list
// containing kValue, k, and O.
var testResult = callbackfn.call(T, kValue, k, O);
// iii. If ToBoolean(testResult) is false, return false.
if (!testResult) {
oneFalse = true;
}
}
k++;
}
return !oneFalse;
};
}
function gt2(element, index, array) {
return element > 2;
}
document.write([1,2,3].everyCheckAll(gt2)); // false
document.write([4,5,6].everyCheckAll(gt2)); // true
Use Array#every, and check that every number is not greater than 2. Another advantage of Array#every is that whenever the callback returns false, the iteration stops, and the result is returned.
const flag = [1, 2, 3].every((n) => n <= 2);
console.log(flag);

Convert object into array in IE (Javascript)

can I convert , in Javascript, an object into an array in Internet Explorer? I read that the method Array.from(obj) is not supported from IE. It is correct?
Thank you
You can verify for yourself on On Mozilla's MDN that Array.from() isn't supported by IE :
On that same page, you can also find the following polyfill to add support of Array.from() to browsers that don't support it natively :
// Production steps of ECMA-262, Edition 6, 22.1.2.1
if (!Array.from) {
Array.from = (function () {
var toStr = Object.prototype.toString;
var isCallable = function (fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function (value) {
var number = Number(value);
if (isNaN(number)) { return 0; }
if (number === 0 || !isFinite(number)) { return number; }
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function (value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike/*, mapFn, thisArg */) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError('Array.from requires an array-like object - not null or undefined');
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
Note that it comes with the following remarks :
This algorithm is
exactly the one specified in ECMA-262, 6th edition, assuming Object
and TypeError have their original values and that callback.call
evaluates to the original value of Function.prototype.call. In
addition, since true iterables can not be polyfilled, this
implementation does not support generic iterables as defined in the
6th edition of ECMA-262.
That means that there are a few caveats, but it should be more than sufficient for most purposes!
Yes, according to ECMAScript 6, this true for elder IE. You can find some polyfills listed there if you need this function & support for elder IE.
Array.from method is a method that came with ECMAScript 6
you can see on this page that the support for ECMAScript 6 in IE is not very good. Look at the examples in the below question for a solution to your problem
Converting a JS object to an array
As in JavaScript, array positions are like object properties (You can access objects with obj["property"]), you can just iterate over the properties of your object and push them onto an array.
For example:
//Example object
var obj = {
prop1: "asd",
prop2: "Another value",
prop3: 5,
funcprop: function(val){return val*2;}
}
//-----------
var i = 0;
var array = [];
for(prop in obj){
array[i] = obj[prop];
i++;
}
console.log(array); //Array [ "asd", "Another value", 5, funcprop() ]
Acording to MSDN, for..in syntax is valid since IE6.
Take this with care, as you will have property functions in the array positions also.

What is the purpose of doing `Object(this)`?

I was going through the Array'a find polyfill implementation on MDN:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find?v=control#Polyfill
Copy pasting it below:
// https://tc39.github.io/ecma262/#sec-array.prototype.find
if (!Array.prototype.find) {
Object.defineProperty(Array.prototype, 'find', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];
// 5. Let k be 0.
var k = 0;
// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return kValue.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return kValue;
}
// e. Increase k by 1.
k++;
}
// 7. Return undefined.
return undefined;
}
});
}
Why is it that we need to do var o = Object(this);?
What does Object(this) achieve?
Thanks for any discussion.
In strict mode, a primitive this will not be coerced to an object.
Therefore, explicit coercion to an object using Object(this) is necessary.
Here is a more detailed example:
const array = Array.prototype;
Object.defineProperty(array, 'foo1', { value() {
return this.length >>> 0; }});
Object.defineProperty(array, 'foo2', { value() {
"use strict";
return this.length >>> 0; }});
console.log(Array.prototype.foo1.call(undefined));
console.log(Array.prototype.foo2.call(undefined));
The first example runs successfully with a result of 0, because the argument undefined is coerced to an object in non-strict mode. The second example fails, because undefined is not coerced in non-strict mode, and thus this.length errors out.
From MDN:
the value passed as this to a function in strict mode is not forced into being an object (a.k.a. "boxed")
However, in this case, there is already an explicit check for null or undefined:
if (this == null) {
throw new TypeError('"this" is null or not defined');
}
so I am tempted to say the explicit casting to an object is not necessary. It is probably used here out of an abundance of caution, or as boilerplate.
This is a fascinating question... Thanks for your post!
To be honest, I am a bit surprised by Object(this) because JavaScript seems to coerce anything to object (using wrappers) in situations where this could potentially be a primitive value.
If we try to change this with Function.prototype.bind(), JavaScript always returns an object (a function is an object):
var foo = function () {
console.log(this, typeof this);
}.bind('foo');
var bar = function () {
console.log(this, typeof this);
}.bind(1337);
var baz = function () {
console.log(this, typeof this);
}.bind(false);
var qux = function () {
console.log(this, typeof this);
}.bind(NaN);
var quux = function () {
console.log(this, typeof this);
}.bind(undefined);
var corge = function () {
console.log(this, typeof this);
}.bind(null);
var grault = function () {
console.log(this, typeof this);
}.bind([]);
var garply = function () {
console.log(this, typeof this);
}.bind({});
var waldo = function () {
console.log(this, typeof this);
}.bind(/regex/);
var fred = function () {
console.log(this, typeof this);
}.bind(function () {});
foo(); // String { 0: "f", 1: "o", 2: "o" } object
bar(); // Number { 1337 } object
baz(); // Boolean { false } object
qux(); // Number { NaN } object
quux(); // Window object
corge(); // Window object
grault(); // Array [ ] object
garply(); // Object { } object
waldo(); // /regex/ object
fred(); // function fred<() function
If we try to change this with Function.prototype.call() or Function.prototype.apply(), once again, JavaScript always returns an object:
Array.prototype.foo = function () {
console.log(this, typeof this);
};
['foo'].foo(); // Array [ "foo" ] object
Array.prototype.foo.call('bar'); // String { 0: "b", 1: "a", 2: "r"} object
Array.prototype.foo.call(42); // Number { 42 } object
Array.prototype.foo.call(true); // Boolean { true } object
Array.prototype.foo.call(NaN); // Number { NaN } object
Array.prototype.foo.call(undefined); // Window object
Array.prototype.foo.call(null); // Window object
Array.prototype.foo.call({}); // Object { } object
Array.prototype.foo.call(/regex/); // /regex/ object
Array.prototype.foo.call(function () {}); // function () function
In JavaScript, we know that native objects may be useful for type conversion when they are not used as constructors but as regular functions. Number, String and Boolean are quite convenient:
var num = 1337,
str = '',
bool = true;
console.log(Number(str), typeof Number(str));
console.log(Number(bool), typeof Number(bool));
console.log(String(num), typeof String(num));
console.log(String(bool), typeof String(bool));
console.log(Boolean(num), typeof Boolean(num))
console.log(Boolean(str), typeof Boolean(str));
For the record, here is what we get with explicit conversions through Object():
console.log(typeof Object(false), Object(false) instanceof Boolean);
console.log(typeof Object('bar'), Object('bar') instanceof String);
console.log(typeof Object(42), Object(42) instanceof Number);
console.log(typeof Object(NaN), Object(NaN) instanceof Number);
console.log(typeof Object(undefined), Object(undefined) instanceof Object);
console.log(typeof Object(null), Object(null) instanceof Object);
console.log(typeof Object(['foo']), Object(['foo']) instanceof Array);
console.log(typeof Object({}), Object({}) instanceof Object);
console.log(typeof Object(/regex/), Object(/regex/) instanceof RegExp);
console.log(typeof Object(function () {}), Object(function () {}) instanceof Function);
Now it is obvious that Object(this) can be used to convert any primitive value for this and get a wrapper object instead. If this is already an object, it has no effect:
var obj1 = {baz: 'Baz'},
obj2 = Object(obj1);
var arr1 = ['foo', 'bar'],
arr2 = Object(arr1);
var reg1 = /regex/,
reg2 = Object(reg1);
var fun1 = function () { return 'Hello!'; },
fun2 = Object(fun1);
console.log(arr1 === arr2);
console.log(obj1 === obj2);
console.log(reg1 === reg2);
console.log(fun1 === fun2);
Moreover, Object is weird because it acts in the same way, whether it is called with new or not:
var foo = Object('foo'),
bar = new Object('bar');
console.log(foo);
console.log(bar);
I may be wrong, but my conclusion is the following: given that this is always coerced to an object, Object(this) is not necessary. However, it indicates explicitly what happens implicitly to avoid ambiguity and improve code comprehension.
What do you think?
EDIT
torazaburo is right: strict mode is the key! When functions are in strict mode, primitive values for this are not coerced! This is probably the most reasonable explanation for explicit conversion with Object(this)...
Function.prototype.bind()
var foo = function () {
'use strict';
console.log(this, typeof this);
}.bind('foo');
var bar = function () {
'use strict';
console.log(this, typeof this);
}.bind(1337);
var baz = function () {
'use strict';
console.log(this, typeof this);
}.bind(false);
var qux = function () {
'use strict';
console.log(this, typeof this);
}.bind(NaN);
var quux = function () {
'use strict';
console.log(this, typeof this);
}.bind(undefined);
var corge = function () {
'use strict';
console.log(this, typeof this);
}.bind(null);
var grault = function () {
'use strict';
console.log(this, typeof this);
}.bind([]);
var garply = function () {
'use strict';
console.log(this, typeof this);
}.bind({});
var waldo = function () {
'use strict';
console.log(this, typeof this);
}.bind(/regex/);
var fred = function () {
'use strict';
console.log(this, typeof this);
}.bind(function () {});
foo(); // foo string
bar(); // 1337 number
baz(); // false boolean
qux(); // NaN number
quux(); // undefined undefined
corge(); // null object
grault(); // Array [ ] object
garply(); // Object { } object
waldo(); // /regex/ object
fred(); // function fred<() function
Function.prototype.call()
Array.prototype.foo = function () {
'use strict';
console.log(this, typeof this);
};
['foo'].foo(); // Array [ "foo" ] object
Array.prototype.foo.call('bar'); // bar string
Array.prototype.foo.call(42); // 42 number
Array.prototype.foo.call(true); // true boolean
Array.prototype.foo.call(NaN); // NaN number
Array.prototype.foo.call(undefined); // undefined undefined
Array.prototype.foo.call(null); // null object
Array.prototype.foo.call({}); // Object { } object
Array.prototype.foo.call(/regex/); // /regex/ object
Array.prototype.foo.call(function () {}); // function () function

What is the use of length property of an Object in Javascript?

This code is polyfill of Array.prototype.map given on Mozilla Developer Network. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this|
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal
// method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len)
// where Array is the standard built-in constructor with that name and
// len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while (k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Let mappedValue be the result of calling the Call internal
// method of callback with T as the this value and argument
// list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor
// { Value: mappedValue,
// Writable: true,
// Enumerable: true,
// Configurable: true },
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, k, {
// value: mappedValue,
// writable: true,
// enumerable: true,
// configurable: true
// });
// For best browser support, use the following:
A[k] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
What I do not understand is these two lines -
var O = Object(this);
var len = O.length >>> 0;
Can someone please explain this to me? What is the use of calling length property on an Object(which has become an array after passing 'this' to it, I suppose) and then zero-fill right shifting it by 0?
Obviously, it needs the length in order to iterate over the elements of the array.
You don't really need to worry about the Object(this). If this is an array, it does nothing. This type of coding is to deal with certain kinds of objects which are not arrays. For instance, I can invoke map as Array.prototype.map.call(5, function() { }) and it will work (returning []). In this case, the line you are wondering about turns 5 into an object, whose length property I can examine (although in that case it doesn't exist; the >>> 0 idiom will transform the undefined into 0).

Categories