I am learning javascript.
var label = document.getElementById('lblMsg');
If I inspect the element with F12, its described as an HTMLSpanElement. I cannot cast the element to its type, like:
var label = (HTMLSpanElement) document.getElementById('lblMsg');
So whats the use for HTMLSpanElement ? Does it have any properties différent than the other HTMLElements ?
Since you are a beginner, I'm going to point out a few basic facts that may help you make some sense of what you are observing.
JavaScript is weakly typed
Objects in JavaScript do have types, but variables are not typed, i.e. any variable can take any object of any type. Type casting is not necessary, nor is it possible (and in fact the line (HTMLSpanElement) document.getElementById('lblMsg') is a syntax error).
HTML elements types
HTMLSpanElement is a type. Well, not really. It's a DOM interface, which is treated as a native object type by all modern browsers for convenience. Most HTML elements have the type of their main interface.
The point of interfaces is to expose a set of methods, properties or events available to all implementations. You already have the MDN link for HTMLSpanElement: https://developer.mozilla.org/en-US/docs/Web/API/HTMLSpanElement.
Testing for a type
To test if an object is an instance of a particular type, we can use obj instanceof Type. In this case:
if (document.getElementById('lblMsg') instanceof HTMLSpanElement)
{
...
}
Type inheritance is always honored.
document.getElementById('lblMsg') instanceof Object // true
Getting an object's type
To get the type of an HTML element, we use element.constructor, as in
document.getElementById('lblMsg').constructor
If you enter this in the browser console, you will see something like
`function HTMLSpanElement() { [native code] }`
Don't be surprised. Object types are functions in JavaScript. If we were just interested in the name of this object's type, we could use
document.getElementById('lblMsg').constructor.name
Which yields the string "HTMLSpanElement"
This method of determining an object's type is not 100% foolproof, but it works for all builtin objects.
Related
I'm working on logic that detects any stateful variables that can be safely saved and restored via JSON as the storage vector.
Part of this means detecting types that are "safe" to dump and restore, which is easy for:
numbers, strings and booleans (via typeof)
Array elements (via instanceof Array combined with ^ in iterated elements)
ES6 Class instances (via typeof object and value.__proto__.constructor.name)
There is one type I'm struggling with though. It's the one created from calling:
var nn = new convnetjs.Net();
Which comes from this:
https://github.com/karpathy/convnetjs/blob/master/src/convnet_net.js#L8
What's interesting is that Chrome dev tools detects this as a "Net" object:
This is what you'll see if you inspect the nn var shown above.
Here's what I've tried:
nn instanceof Object === true
Object.getPrototypeOf(nn) - interestingly, this exposes the functions assigned to Net.prototype in the link above, line 12 onwards. Seemed like a lead.
Object.getPrototypeOf(nn).toString() == [object Object]
Object.getPrototypeOf(nn) instanceof Object === true. Makes sense, since it's an object containing custom functions attached to the prototype.
Object.getPrototypeOf(nn).constructor.name === Object
Would anyone know or have ideas how I could detect this type of object safely? Plain objects are fine, but I don't want to overwrite objects with modified prototypes.
If resorted to using this to verify it this is a plain object or one with custom prototypes:
const isPlainObject = Object.getPrototypeOf(value) === Object.getPrototypeOf({});
I am creating a scriptable application using the native windows API and the chakrart JavaScript engine.
I have interfaces like the following in my IDL:
[oleautomation, dual, nonextensible,
uuid(...)]
interface IMyInterface : IDispatch
{
[id(MYDISPID_EVENT), propget] HRESULT Event(BSTR strEventName, [out, retval] IDispatch ** ppHandler);
[id(MYDISPID_EVENT), propput] HRESULT Event(BSTR strEventName, IDispatch * pHandler);
};
I have been able to add the native objects to the chakrart engine without trouble (by using JsVariantToValue and then setting a property on the global object of the current context). However when I attempt to set an event handler I get the exception message 'Object doesn't support this property or method'.
I have tried the following syntax variations:
object.Event["foo"] = handler;
object.Event("foo", handler);
object.put_Event("foo", handler);
object.Event("foo") = handler;
That last is close to how this would be done using vbscript:
object.Event("foo") = GetRef("handler)
If I use method syntax in the IDL like the following it works, I would simply prefer to use property assignment if possible.
[id(MYDISPID_GETEVENT)] HRESULT GetEvent(BSTR strEventName, [out, retval] IDispatch ** ppHandler);
[id(MYDISPID_SETEVENT)] HRESULT SetEvent(BSTR strEventName, IDispatch * pHandler);
And also note that simple property assignments do work, it is only when I try indexed properties that it breaks. I do understand that JavaScript does something very different with object[prop] syntax, at least for native JavaScript objects. Is this perhaps simply an incompatibility in the chakrart interop layer?
I have confirmed a way to perform this with the desired syntax (App.Event['foo'] = someHandler;). As mentioned I already knew JavaScript treats name['foo'] as a member lookup on name
Have the App object implement a propget for Event that returns an object with a custom (non-dual interface) IDispatch implementation. That object keeps a map of names to DISPIDs and whenever an unknown name is requested via GetIDsOfNames a previously unassigned DISPID is returned.
Note that in order to comply with the rules for IDispatch the object needs to keep track of names even if a null handler is later assigned to a given name, so that the same DISPID will always be returned for a particular name.
I'm currently doing a bit of JavaScript and I have some troubles trying to explain myself one thing.
If I do that :
var text = new String("Enter any value here");
We all agree that "text" is an object, right?
But what should be "String" called then? Because I see everywhere that String is also an object, but wouldn't it be simpler to call it a class like in PhP.
Is there an other name, more precise than just object for String?
If someone can explain me the subtlety, I would be very happy. Thank you!
I think the source of your confusion is unfamiliarity with Prototypal Inheritance model. I suppose you are well versed with 'Classical Model' where classes are constructed using Classes as blueprint. On the other hand in JavaScript other Objects are created using an Object as a prototype or using an empty object and then pinning new properties in it.
If you try logging typeof(String) you will get output as function. Here when we do a new String('hello, world'), we get a new String object Hello, World. Thus String is a constructor in JavaScript.
By design, JavaScript (the implementation of the ECMAScript standard) has no class. So String cannot ever be called a class.
String here is but an object, just as almost everything in JavaScript is (as some the answers have already stated).
console.log(String instanceof Object); // true
Actually a special object: a function.
console.log(typeof String); // "function"
console.log(String instanceof Function); // true
And even a special function: a function that should be called as a constructor, hence the capital 'S'.
Even more special function: it is a built-in function (it is "present in the language" and therefore provided by the host environment -the browser or node, for example).
This special function allows you to instantiate an object of type String:
var aString = new String("A string");
But this is the wrong way to do it: you should write this:
var aPrimitiveString = "A string";
which interestingly, by the way, doesn't make text a String (Object), but a string (primitive).
console.log(typeof(aString)); // "object"
console.log(aString instanceof String); // true
console.log(aString instanceof Object); // true
console.log(typeof(aPrimitiveString)); // "string"
console.log(aPrimitiveString instanceof String); // false
console.log(aPrimitiveString instanceof Object); // false
Even in ECMAScript 6 (AKA ES6, AKA Harmony, AKA ES2016), there won't be any classes in the acception you have of it, "classes" in ES6 will still be an object, of type function, with prototypal inheritance.
One more thing: String can also be used to explicitly coerce a value into a string primitive:
var number = 1;
var numberAsString = String(1);
console.log(number); // 1
console.log(numberAsString); // "1"
console.log(typeof number); // "number"
console.log(typeof numberAsString); "string"
for the sake of completeness, I hope you guessed that:
number is a primitive number
numberAsString is a primitive string
new number(1) would be an object, instance of Number and Object
Number('0') would be a primitive number
same goes for Boolean
There are no classes in JavaScript, there won't ever be (I don't want any of it, anyway), that is what make the language so flexible, expressive and powerful.
Maybe you would want to take a look at this: http://javascript.crockford.com/inheritance.html (and the whole site and work of Douglas Crockford).
JavaScript is an object oriented language without classes.
However, you can apply many object oriented paradigms in JavaScript. It has its own mechanisms to do so.
In JavaScript, instead of classes you use objects. That's really about it already. You can think of String as a class if you want, but sometimes it can lead to confusion, because it is easy to confuse concepts known from Java or C++ with JavaScript. The implementation is just different.
I suggest you omit to think of it as a class, and call it an object. And try not to apply terminology of other languages like PHP with JavaScript.
Now, the confusion might be that in other OO languages you define a class and then you create instances from that class, which we refer to as objects.
In JavaScript you simply create a new copy of another object.
Please refer to this link and...
...note that JavaScript distinguishes between String objects and
primitive string values. (The same is true of Boolean and Numbers.)
According to w3schools:
In JavaScript, almost "everything" is an object.
Booleans can be objects (or primitive data treated as objects)
Numbers can be objects (or primitive data treated as objects)
Strings can be objects (or primitive data treated as objects)
Dates are always objects
Maths are always objects
Regular expressions are always objects
Arrays are always objects
Functions are always objects
Objects are objects
In JavaScript, all values, except primitive values, are objects.
Primitive values are: strings ("John Doe"), numbers (3.14), true,
false, null, and undefined.
MDN says in javascript everything are objects.
In JavaScript, almost everything is an object. All primitive types
except null and undefined are treated as objects. They can be assigned
properties (assigned properties of some types are not persistent), and
they have all characteristics of objects.
Creating new objects
JavaScript has a number of predefined objects. In addition, you can
create your own objects. You can create an object using an object
initializer. Alternatively, you can first create a constructor
function and then instantiate an object using that function and the
new operator.
So in javascript the idea of class doesn't really exist like in other languages. It's just an instantiated object or function if you prefer.
typeof 1.00 // number
typeof 1 //number
typeof "string" //string
typeof String("string") //string
typeof new String("string") //object
typeof {} //object
typeof [] //object
Demo
It seems possible to create classes in ECMAScript 6
It is said that:
Defining classes
Classes are in fact functions, and just like you can define function
expressions and function declarations, the class syntax has the two
opponents:
class expressions and class declarations.
At one popular blog, the author asked his audience what was their “Ah ha!” moment for JavaScript and most of the people said that it was realizing that everything in JavaScript is an object.
But being new to JS and programming in general I don't quite get what that means. It doesn't seam like it's related to actual JS Object - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
Or it does?
If it doesn't could you please explain what do they mean by "everything in JavaScript is an object".
Or it's all about OO Programming in general and reading something on this subject will help to understand it? Can you recommend what to read on this topic?
Go back to first principles.
What's an object? It's a software component that encapsulates state and behavior together into a single entity in memory.
By that definition, you can see where everything can be thought of as an object. Functional programmers make functions first class objects. Data folks would say that data, even that without behavior, can be thought of as an object (albeit not a very smart one).
I don't see what this changes.
JavaScript treats functions as objects.
I'm not sure what effect this insight will have on your programming.
What they mean, most likely, is that any data that can be assigned to a variable has properties (and therefore methods) that can be accessed in an object like fashion.
// strings
"asdf".length; // 4
"asdf".replace('f', 'zxc'); // "azxc"
// numbers
(10).toFixed(2); // "10.00"
// booleans
true.someProp; // undefined (point is it doesn't crash)
They even have prototypes they inherit from.
"omg".constructor; // function String() { [native code] }
String.prototype.snazzify = function() {
return "*!*!*" + this + "*!*!*";
};
"omg".snazzify(); // "*!*!*omg*!*!*"
However, these are primitives, and while they behave object like in a lot of ways, they are different from other "real" JS objects in a few ways. The biggest of which is that they are immutable.
var s = "qwerty";
s.foo; // undefined, but does not crash
s.foo = 'some val'; // try to add a property to the string
s.foo; // still undefined, you cannot modify a primitive
Do note though that functions are real mutable objects.
var fn = function(){};
fn.foo; // undefined
fn.foo = 'some val'; // try to add a property to the function
fn.foo; // "some val"
So while it's not technically true that "everything in JS is an object", under most circumstances you can treat them mostly like objects in that they have properties and methods, and can potentially be extended. Just be sure you understand the caveats.
NOT everything in JavaScript is an object.
All data in JavaScript must fall into one of six primitive types, or the object type. Primitive types includes boolean, null, undefined, string, number and symbol; everything that is not a primitive is an object.
This means functions are objects, arrays are objects, ES6 classes de-sugars into a function which are objects.
The confusion arises because primitive values have object wrappers. When you try to access the length property on the string literal, JavaScript creates a temporary object wrapper around the primitive and access the length property of that object wrapper. After the property has been retrieved, the object wrapper is discarded. This is known as autoboxing.
Essentially, it is implemented similar to the following:
const foo = "bar";
// When you run `foo.length`, it's similar to
tmp = String(foo);
tmp.length;
delete tmp;
Or
const foo = "bar";
(new String(foo)).length;
The string, number and boolean primitives have object wrappers, but null and undefined do not. So trying to access a property or method from those primitives would throw an error.
null.length; // Uncaught TypeError: Cannot read property 'length' of null
undefined.length; // Uncaught TypeError: Cannot read property 'length' of undefined
Not everything is an object in JavaScript. For example a number is not an object.
Different languages have different definition of "object". For JavaScript, the official definitions can be found in the ECMAScript Language Specification, which states:
In ECMAScript, an object is a collection of zero or more properties
each with attributes that determine how each property can be used (...) Properties are containers that hold other objects,
primitive values, or functions. A primitive value is a member of one
of the following built-in types: Undefined, Null, Boolean, Number,
BigInt, String, and Symbol; an object is a member of the built-in type
Object; and a function is a callable object.
So by this definition it is clear that primitive values (like numbers) are not objects. Even strings are not objects, which is different from most other OO languages.
So why do some people say "everything is an object"? You have to ask them! But I suspect it is because they are getting confused by the built-in objects Number, Boolean, String etc. which can be used as wrappers around the corresponding primitive values. This wrapping sometimes happen automatically, which can make primitive values look like object and for example allow you to (seemingly) access properties on primitives. But in reality the properties are on the wrapper object.
'ALMOST everything is an object' because the MAIN code-units are JS-objects. On primitives you can NOT add members for example as on all objects. My answer why JS-functions are JS-objects here: https://stackoverflow.com/a/24811539
Question is self explanatory. I know it is possible to extend primitive data types such as string but is it possible to overwrite it?
This is a question that has been asked in an interview.
No, you cannot overwrite anything. EcmaScript defines the primitive types Undefined, Null, Boolean, Number, and String; these are internal and will be used regardless of what you are doing (for example overwriting the global String constructor). Type conversion and evaluation of literals does not rely on any public functions but uses only these internal types and the algorithms specified for them.
Of course, if someone does string coercion with String(myval) instead of ""+myval assigning to the global String variable will have an effect on that code. Any internal use would still point to the "old" function.
If you were talking about prototype objects for the primitive types (when used as objects), those are not overwritable as well. You may extend those objects, but as soon as you assign to e.g. Number.prototype you just have lost a reference to the actual, original number protype object. Example spec for The Number constructor:
The [prototype] of the newly constructed object is set to the original Number prototype object, the one that is the initial value of Number.prototype (15.7.3.1)
Yes (edit: almost). Open up a Javascript console (F12 if you're using Chrome) and type
String = function(){alert('bang!')};
You can overwrite (edit: almost) everything in Javascript — even the window global context! evil.js is a library that uses this trick to rewrite many native objects as possible.
Needless to say, this is extremely dangerous. I performed the String remapping code above, and since writing it down I've caused over 520 Javascript errors (and I've seen 'bang' alerted quite a few times). Native objects are used everywhere, and you shouldn't modify these in case 3rd party code relies on them in ways you don't know about. This is one of the reasons Prototype.js lost popularity — because its extension of native objects would often work against the expectations of other code.
Edit: Factually incorrect assertion that absolutely everything could be overwritten, as pointed out in Bergi's answer. Edits made inline.
You can extend prototypes of native types.
String.prototype.moo = function() {
console.log( 'Moo!' )
};
'Cow says'.moo();
>> "Moo!"
However you cannot directly overwrite constructors of built-in types unless you overwrite the reference to the entire object:
String = function() {
console.log( 'Custom function.' )
};
new String( 'Hello!' );
>> "Custom function."
>> String {} // now you've broken your website ;)
...but still:
'Wat?!'
>> "Wat?!" // you can still create strings by typing letters in quotes
So... the answer is "yes but no". You can mess with native types (Number, Date, String...) but you cannot re-define them entirely from scratch. They're a part of JS engine that you're using (most likely native C++ code) and this brings some limitations.
Possible like this but you must always succeed without side effects.Not good practice.
function Array() {
var obj = this;
var ind = 0;
var getNext = function(x) {
obj[ind++] setter = getNext;
if (x) alert("Data stolen from array: " + x.toString());
};
this[ind++] setter = getNext;
}
var a = ["private stuff"];
// alert("Data stolen from array: private stuff");