Edit In regard of Barmar request, I upload this screenshot. As Jake claims, this is about that statement.
In this article MDN explains some details on JS inheritance, including a meant demonstration of why JS classic model of inheritance is safer than JS classes. They did many useful things in this text, but I don't see this particular point demonstrated. Could somebody point out the MDN arguments that demonstrate how traditional syntax is safer than classes syntax?
Thank you
Bonus: I did this short version of "The employee example" implemented in the mentioned article. According to this, traditional syntax is not safer, but rather longer and difficult to follow:
//TRADITIONAL SYNTAX
function Participant ({gender, tastes}){
this.gender = gender;
this.tastes = tastes || [];
}
function NotPayer({gender, tastes, role}){
this.role = role || 'kid';
this.base = Participant;
this.job = 'Not Valid';
this.base({gender, tastes});
}
NotPayer.prototype = Participant.prototype;
const kid1 = new NotPayer({role: 'nephew', gender: 'male', tastes: ['golf']});
console.log(kid1.gender); //male
const kid2 = new Participant({gender: 'female'});
console.log(kid2.gender); // female
//MODERN SYNTAX
class Participant {
constructor({gender, tastes}){
this.gender = gender;
this.tastes = tastes || [];
}
}
class NotPayer extends Participant {
constructor({gender, tastes, role}){
super({gender, tastes});
this.role = role || 'kid';
}
}
const kid1 = new NotPayer({role: 'nephew', gender: 'male', tastes: ['golf']});
console.log(kid1.gender);//male
const kid2 = new Participant({tastes: ['dance'], gender: 'female2'});
console.log(kid2.gender);// 'female2'
The text in article is a caption for the code sample below it. It says
JavaScript (using this may cause an error for the following examples)
and then goes on to show an example of class syntax. Immediately following that example is a caption saying
JavaScript ** (use this instead)
followed by an example of a (constructor) function syntax.
It then shows how Java does classes. Then the article talks a little about prototypal inheritance, a key part of JavaScript's object oriented design prior to the introduction of classes, and follows up with examples of that type of inheritance.
It is in these examples where, if one used the class syntax example introduced originally, the code would fail.
Just for giggles, here's a Stack Snippet showing what happens:
class Employee {
constructor() {
this.name = '';
this.dept = 'general';
}
}
function Manager() {
Employee.call(this);
this.reports = [];
}
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;
console.log(new Manager());
The error that arises (Uncaught TypeError: Class constructor Employee cannot be invoked without 'new') when you click Run code snippet here (on a suitably modern browser) is what that "using this may cause an error" text is talking about. That "for the following examples" is a key part of the phrase.
The MDN warning regards that the examples developed in the article could not run in some engines, rather than suggests that traditional syntax is better than modern syntax. As Ashish and Jake pointed out this is related to JS engines support for classes syntax.
Even though, I think that the MDN article could be even more explicit about that (since, the argumentation regards many complex subjects.)
Related
Read about constructors in functions:
function Animal(name) {
this.name = name;
this.canWalk = true;
}
var animal = new Animal("Hedgehog");
and also about prototypes:
Animal.prototype.draw = function () {
}
But until the end I did not understand exactly how they reduce the code and, in principle, improve the life of programmers. Why? Because it is better understood on real examples from sites and not on examples of animal or "hedgehogs" of all sorts.
An example from my personal experience: I started the cycles well when I needed to prescribe a function for 30 images, but instead of 30 functions I passed one function into a cycle and reduced it the way the code, so I understood the whole essence of the cycle, and not just memorized its anatomy. That would be for learning resources to make examples of real projects beginners would not ask 100 questions of the same type.
Therefore, I have such questions:
Can you write here how the code would look at first without a prototype and then with a prototype on some small example from the site? Or an example that could be implemented on which site.
Can you write here how the code would look at first without a constructor and then with a prototype on some small example from the site? Or an example that could be implemented on which site.
But do not post in the responses or comments a link from the GitHuB with a large code. Just give a small example here. And it is desirable not an example from the game, but from the site
Using an object constructor is a way to initialize an instance with a specific functionality. In most cases it is used to initialize properties with values (like in your code), but can be used for other things as well.
Let use more realistic example - I can initialize a few users object simply by object literals:
const user1 = {
id: 'usr123',
name: 'Max',
questions: 4
}
const user2 = {
id: 'usr124',
name: 'Danny',
questions: 2
}
But there are few problems with this approach.
First, it can be tedious when used a lot.
Second, it's harder to distinguish it from other objects.
Both of these issues can be solved with construction function:
function User(id, name, questions) {
this.id = id;
this.name = name;
this.questions = questions ? questions : 0;
}
const user1 = new User('usr123', 'Max', 4);
const user2 = new User('usr125', 'Ben'); // default questions value would be 0
const isUser = user1 instanceof User; // true
Prototype is a special object which can be used on Objects which has a constructor function (Well, all objects are descendant of Object, but let's leave this aside for a moment). The basic idea is - if I have 100 user objects - I might have some use for have a special properties or logic which relevant for all of them, and not specific for a single instance. For example, let's assume that in case of error, I would like to log all the data of the users.
I can create a special function which get and object and do this:
function userToString(user) {
return user.id + ':' + user.name + '[' + user.questions + ']'; // usr123:Max[4]
}
This would work, but harder to maintain, since it is not really part of "User".
I large projects I would probably put this function in a file with other utilities function, and call it every time i would like to use it.
Another option is to include it as part of the prototype:
User.prototype.toString() {
return this.id + ':' + this.name + '[' + this.questions + ']';
}
user1.toString(); // usr123:Max[4]
I would strongly suggest to using ES6 standard (at least). It's exist for several years, it looks much more intuitive and do some of the complex work for you.
In ES6 this code would look like this:
class User {
constructor(id, name, questions) {
this.id = id;
this.name = name;
this.questions = questions ? questions : 0;
}
toString() {
return this.id + ':' + this.name + '[' + this.questions + ']';
}
}
Look nicer isn't it? but it basically the same. This ES6 syntax is simply sugar coating for the older syntax you've included in your question.
I wonder which approach is better for creating functions in JavaScript classes:
Having a list of functions each dedicated to one specific operation.
Having a general purpose function that takes arguments to decide what to execute.
My belief is the first option provides a nice interface but may cause redundant code, and second option is clean and flexible but may become confusing to use.
I really did not know how to ask this question, so I would like to explain it by a code example.
Suppose we have these Classes for printing names of creatures.
class GeneralPurposePrint {
constructor (args) {
this.isHuman = args.isHuman || false;
this.isOld = args.isOld || false;
this.name = args.name || "Nameless"
}
//This is what I mean by "general purpose function"
//arguments may as well come with the printName functions...
printName(){
const type = this.isHuman ? "the human" : "the animal";
const age = this.isOld ? "Old" : "Young";
console.log(`${age} ${this.name} ${type}`)
}
}
class DedicatedPrint {
constructor (name) {
this.name = name;
}
//And by dedicated functions I mean the following functions here
printOldHuman() {
console.log("Old human", this.name, "the human")
}
printYoungHuman() {
console.log("Young", this.name, "the human")
}
printOldAnimal() {
console.log("Old", this.name, "the animal")
}
printYoungAnimal() {
console.log("Young", this.name, "the animal")
}
}
This question is out of pure curiosity and maybe it's best to use both of the approaches. And please don't mind the funky code example I wrote, you may think of the similar structure for a class for choosing a sorting algorithm, a type of connection, creating a shape or such.
Thats rather a design decision, so you should ask yourself does GeneralPurposePrint really get old or is it really sometimes human and sometimes not? If not that definetly shouldn't be properties of the class. To reduce the redundant code of the second approach you could just pass in arguments to the method:
printName(old, human) {
console.log((old ? "Old" : "Young") + this.name + (human ? "the human" : "the animal"));
}
This question already has answers here:
Why doesn't JavaScript ES6 support multi-constructor classes?
(8 answers)
Closed 6 years ago.
Objective
Implement a mechanism to allow constructor overload in JavaScript ECMA6
Why this is not a duplicate
The topic Why doesn't JavaScript ES6 support multi-constructor classes?, although similar is not the same as this one. The other topic merely focuses on a constructor overloading using the old ECMAScript versions, while this topic focuses on ECMA6. If you are looking for an updated answer, this is the place.
Background
I have a JavaScript class with a given constructor, and I want the user to be able to have different constructors when instantiating an object. An example of what I pretend could be the following:
const DEFAULT_WHEEL_NUMBER = 4;
const DEFAULT_COLOR = "black";
const DEFAULT_NAME = "myCar";
class Car{
constructor(numberWheels, aName, aColor){
this.wheelsNum = numberWheels;
this.name = aName;
this.color = aColor;
}
constructor(aName){
this(DEFUALT_WHEEL_NUMBER, aName, DEFAULT_COLOR);
}
constructor(){
this(DEFUALT_WHEEL_NUMBER, DEFAULT_NAME, DEFAULT_COLOR);
}
}
In this code, the user has three constructors he can use, each one taking a different amount of parameters. An usage example follows:
var car1 = new Car(3, "tricicle-car", "white");
var car2 = new Car("Opel"); //creates black car with 4 wheels called Opel
var car3 = new Car(); //creates a black car, with 4 wheels called myCar
Problem
This is a straightforward example if one is using Java or C#, because those languages have constructor overloads.
However, from the documentation on classes from MDN one can conclude that JavaScript does not.
Question
Is there a way to implement a similar mechanism for JavaScript classes using ECMA6? If not, what is the best/closest alternative?
There is no in-built solution for this in JavaScript. An alternative solution can be using the arguments object (in some cases), or passing your own configuration options, similar to this:
const defaults = {
numberWheels: 4,
color: "black",
name: "myCar"
}
class Car {
constructor(options) {
this.wheelsNum = options.numberWheels || defaults.numberWheels;
this.name = options.name || defaults.name;
this.color = options.color || defaults.color;
}
}
This is basically the old school solution, I use the same logic in ES3.
You're right (as far as I know) that this isn't a feature JavaScript classes support. My recommendation here, since you're already making use of ES6 features, would be to make use of default parameters instead:
class Car {
constructor(numberWheels = 4, aName = "myCar", aColor = "black"){
this.wheelsNum = numberWheels;
this.name = aName;
this.color = aColor;
}
}
This obviously comes with the caveat that you can't have 'overloads' with different parameter orders like you do in your example (although in my opinion, that's a good thing - a consistent API is much nicer to work with).
meskobalazs's answer is also a good option, especially if you have a lot of options that you want your object to take in. Doing that through function params like this can get a bit messy!
I understand how to instantiate objects and call them, but I just cannot find a reason to use them in my script. I could do
var obj = {
hi: function() {
return "Hello";
}
};
but why can't I just do it the same way like:
function hi() {
return "Hello";
}
I've never understood the reasons why I should use prototyping either. Most of the things I do in JavaScript I can do well without objects. But I want to use objects. What are objects for and what are the reasons why I should use them?
Objects are useful for example for making a single unit out of values that belong together. Example:
function Person(firstName, lastName, gender, age) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.age = age;
}
Person.prototype = {
getFullName: function() { return this.firstName + ' ' + this.lastName; },
isMale: function() { return this.gender == 'Male'; },
isFemale: function() { return this.gender == 'Female'; }
};
var amanda = new Person('Amanda', 'Smith', "Female", 42);
var john = new Person('John', 'Doe', 'Male', 72);
alert(amanda.getFullName());
alert(john.isMale());
Compared to the less structured:
function getFullName(firstName, lastName) {
return firstName + ' ' + lastName;
}
function isMale(gender) {
return gender == 'Male';
}
function isFemale(gender) {
return gender == 'Female';
}
var amandaFirstName = 'Amanda';
var amandaLastName = 'Smith';
var amandaGender = 'Female';
var amandaAge = 42;
var johnFirstName = 'John';
var johnLastName = 'Doe';
var johnGender = 'Male';
var johnAge = 72;
alert(getFullName(amandaFirstName, amandaLastName));
alert(isMale(johnGender));
Objects are useful because
They are stateful.
They can store relations between strings and data.
It can be easier to decompose a problem by breaking it up into objects that collect related operations and state.
If you don't need non-global state, have no need of lookup tables, and your problem is small or more easily decomposed functionally then don't use objects.
Without what you are referring to as objects, you are going to have loose functions all over the place. This very often will result in code that is very difficult to maintain. At a bare minimum objects give you the ability to lump functions together in order to simulate namespaces-- and that's at a bare minimum.
In your simple example, it makes indeed no sense to write a semi "class" / object to hold that method. But when your code grows, you're getting more and more functions and methods, you don't really want to have them all in one big (global) namespace. That is just so impossible to maintenain, no one will understand that code including you at some later point.
That is the first good reason to wrap methods together in an object/"class". Another good reason is re-usabilty. If you're writting objects which are able to inherit their methods, you can re-create another object and abstract it from there on. Most simple concept, but you want to use it if you're describing "things" in your application as module/object.
It tries to simulate the OOP paradigm that's all. There are various ways of doing this. But ask yourself, doe 'hi' belong in 'obj' or can it be a standalone function? Its all about how closely related is the function to the object. Does the function needs to access the objects private variables and such?
This is less of a "objects in Javascript" and more of an objects in general" question.
I'd say the most relevant Javascript The only thing Javascript specific about objects is their neat use when namespacing. For example, most Javascript libraries pack all their stuff in a single object to avoid namespace collision:
dojo.create( ... )
dojo.connect( ... )
As for the other questions of why OOP, there are 2 basic things I think OOP excels at (generic, dumb, examples follow):
Dynamic dispatching - get rid of "ifs" and put responsabilitty where it belongs
When you look at a code that has tons of "switchs":
function doStuff(animal){
if animal is a tiger:
print_tiger_roar();
else if animal is a cow
print_cow_moo();
if animal is a tiger:
print_tiger_wants_meat();
else if animal is a cow
print cow_wants_grass();
It might be a good idea to bundle each different kind of behaviour in a different kind of object and use dynamic dispatching instead:
function doStuff(animal):
animal.print_speak();
animal.print_food_type();
Now, if you come up with another kind of animal in the future, you don't need to go looking around your code to add it - all you need to do is create a new class with the appropriate print_speack and print_food_type methods and the rest of the code won't notice a thing.
Inheritance + reusing methods
In a normal OO language each object stores (and spends memory) for its instance variables, while all methods + static variables are stored in a single place by the class. Javascript doesn't have classes, but it has prototypes and they serve the same basic function in the end.
Some generic thoughts concerning "Why" part:
Objects exist to communicate. It is a common vocabulary for everyone involved in a project. People are used to operate with things (objects) and their operations (messages or methods), rather than just with disconnected actions (functions).
this is my code:
<script type="text/javascript">
var Note=function(){}
Note.prototype = {
get id()
{
if (!("_id" in this))
this._id = 0;
return this._id;
},
set id(x)
{
this._id = x;
}
}
var a=new Note()
alert(a.id)
</script>
this style is like to python ,
this is my first time to see this code ,
and can you give me more example about 'get' and 'set' in javascript .
thanks
Yes it does. This feature was added in ECMAScript 5.
PropertyAssignment:
PropertyName : AssignmentExpression
get PropertyName() { FunctionBody }
set PropertyName( PropertySetParameterList ) { FunctionBody }
Here are a few things to remember when using this syntax.
If your object literal has a value property it cannot have getter or setter and vice versa.
Your object literal cannot have more than one getter or setter with the same name.
A better way to actually use this feature is through the Object.defineProperty function.
function Person(fName, lName) {
var _name = fName + " " + lName;
Object.defineProperty(this, "name", {
configurable: false, // Immutable properties!
get: function() { return _name; }
});
}
This allows you to have nice clean objects with encapsulation.
var matt = new Person("Matt", "Richards");
console.log(matt.name); // Prints "Matt Richards"
It can in certain engines, and it's in the spec for EcmaScript 5, so it should be more widely adopted in the future. The Compatibility Table doesn't direclty address this, but it will likely follow defineProperties, which provides an API for doing the same thing. As pointed out previously, John Resig has a nice article on the new object and property APIs.
Javascript does in fact support getters and setters now. John Resig has a good blog post about them here.
John's article does a good job at mentioning several different ways of defining getters/setters on Javascript objects, but doesn't do a good job at describing when each method is applicable. I believe that is much more effectively accomplished in a more recent blog post by Robert Nyman:
Getters and setters with JavaScript
(this article also introduces the ECMAScript Standard Object.defineProperty)
Yes it can. Here is a nice post about it from John Resig, the creator of jQuery:
JavaScript Getters and Setters