1 overview
The traditional method of JavaScript language is to define and generate new objects by using constructors. Here is an example.
function point (x, y) {
this.x = x;
This.y = y;
}
Point.prototype.toString = function () {return
' (' + this.x + ', ' + this.y + ') ';
var p = new Point (1, 2);
The above is very different from the traditional object-oriented language, such as C + + and Java, and it is easy to confuse the new programmer who is learning the language.
ES6 provides a closer approach to the traditional language, introducing the concept of Class (Class) as a template for objects. The class keyword allows you to define classes. Basically, ES6 class can be regarded as just a grammatical sugar, most of its functions, ES5 can be done, the new class writing is only to make the object prototype more clear, more like object-oriented programming syntax. The code above is rewritten with the ES6 "class", which is the following.
Define class class point
{
constructor (x, y) {
this.x = x;
This.y = y;
}
ToString () {return
' (' + this.x + ', ' + this.y + ') ';
}
}
The code above defines a "class" that can be seen with a constructor method, which is the construction method, and the This keyword represents the instance object. In other words, ES5 's constructor point corresponds to the construction method of the ES6 point class.
The point class also defines a ToString method, in addition to constructing a method. Note that when you define a "class" method, you do not need to add a function to the keyword, just put it in. In addition, there is no need for commas between the methods and an error is added.
The ES6 class can be considered as another form of the constructor function.
Class Point {
//...
}
typeof point//' function ' point
= = Point.prototype.constructor//True
The code above shows that the data type of a class is a function, and the class itself points to the constructor.
When used, it is also directly to the class using the new command, exactly the same as the constructor usage.
Class Bar {
Dostuff () {
console.log (' stuff ');
}
}
var B = new Bar ();
B.dostuff ()///"stuff"
The prototype property of the constructor, which continues to exist on the ES6 "class". In fact, all the methods of a class are defined above the prototype property of the class.
Class Point {
constructor () {
//...
}
ToString () {
//...
}
Tovalue () {
//...
}
} equivalent to
point.prototype = {
toString () {},
Tovalue () {}
};
Invoking a method above an instance of a class is actually invoking a method on the prototype.
Class B {} let
B = new B ();
B.constructor = = B.prototype.constructor//True
In the code above, B is an example of Class B, and its constructor method is the constructor method of Class B prototypes.
Because the methods of the class are defined above the prototype object, a new method of the class can be added to the prototype object. The Object.assign method makes it easy to add multiple methods to a class at once.
Class Point {
constructor () {
//...
}
}}
Object.assign (Point.prototype, {
toString () {},
Tovalue () {}
});
The constructor attribute of the prototype object directly points to the "class" itself, which is consistent with the ES5 behavior.
Point.prototype.constructor = = Point//True
In addition, all defined methods within a class are not enumerable (non-enumerable).
Class Point {
constructor (x, y) {
//...
}
ToString () {
//...
}
}
Object.keys (Point.prototype)
//[]
object.getownpropertynames (point.prototype)
//["Constructor", " ToString "]
In the code above, the ToString method is a method defined inside the point class, which is not enumerable. This is inconsistent with the behavior of ES5.
var point = function (x, y) {
//...
};
Point.prototype.toString = function () {
//...
};
Object.keys (Point.prototype)
//["toString"]
object.getownpropertynames (point.prototype)
//[" Constructor "," ToString "]
The above code uses ES5, and the ToString method is enumerable.
Property name of the class, you can use an expression.
Let methodname = "Getarea";
Class Square {
Constructor (length) {
//...
}
[MethodName] () {
// ...
}
}
In the code above, the square class's method name is Getarea and is obtained from an expression.
2 Constructor method
The constructor method is the default method of a class that is automatically invoked when an object instance is generated from the new command. A class must have a constructor method, and if not explicitly defined, an empty constructor method is added by default.
The constructor method returns the instance object (that is, this) by default, and it is entirely possible to specify that another object is returned.
Class Foo {
constructor () {return
object.create (null);
}
}
New Foo () instanceof foo
//False
In the code above, the constructor function returns an entirely new object, resulting in an instance object that is not an instance of the Foo class.
class, which cannot be invoked without new, and an error will be used. This is a major difference from the normal constructor, which can be executed without new.
Class Foo {
constructor () {return
object.create (null);
}
}
Foo ()
//Typeerror:class constructor Foo cannot be invoked without ' new '
Instance object of Class 3
The instance object of the generated class is written in exactly the same way as ES5, using the new command. If you forget to add new, call class like a function, you will get an error.
error
var point = Point (2, 3); correct
var point = new Point (2, 3);
As with ES5, the properties of an instance are defined on the prototype (that is, defined on class) unless explicitly defined in itself (that is, defined on the This object).
Define class class point
{
constructor (x, y) {
this.x = x;
This.y = y;
}
ToString () {return
' (' + this.x + ', ' + this.y + ') ';
}
}
var point = new Point (2, 3);
Point.tostring ()//(2, 3)
point.hasownproperty (' x ')//True
point.hasownproperty (' y ')//True
Point.hasownproperty (' tostring ')//False
Point.__proto__.hasownproperty (' tostring ')//True
In the above code, both x and Y are attributes of the instance object point itself (because it is defined on the this variable), so the hasOwnProperty method returns True, and ToString is the property of the prototype object (because it is defined on the point Class). So the hasOwnProperty method returns false. These are consistent with the behavior of ES5.
As with ES5, all instances of a class share a prototype object.
var p1 = new Point (2, 3);
var P2 = new Point (3, 2);
p1.__proto__ = = p2.__proto__
//true
In the code above, both P1 and P2 are instances of point, and their prototypes are point, so the __proto__ attribute is equal.
This also means that you can add a method to the Class by using the __proto__ property of the instance.
var p1 = new Point (2, 3);
var P2 = new Point (3, 2);
P1.__proto__.printname = function () {return
' Oops '
};
P1.printname ()//"Oops"
p2.printname ()//"Oops"
var p3 = new Point (4, 2);
P3.printname ()///"Oops"
The code above adds a Printname method to the P1 prototype, and P2 can call this method because the prototype of the P1 is P2. Also, the new instance P3 can call this method after that. This means that using the __proto__ property of an instance to rewrite the prototype must be very cautious and deprecated, because it changes the original definition of Class and affects all instances.
4 There is no variable elevation.
Class does not exist variable elevation (hoist), which is completely different from ES5.
New Foo (); Referenceerror
class Foo {}
In the code above, the Foo class is used before, defined in the post, which will cause an error because ES6 does not elevate the declaration of the class to the head of the code. The reason for this is related to the inheritance to be mentioned below, and it must be guaranteed that subclasses are defined after the parent class.
Let Foo = class {};
Class Bar extends Foo {}
The code above does not complain, because Foo is already defined when class inherits Foo. However, if there is a class elevation, the above code will error, because class will be promoted to the head of the code, and let command is not promoted, so that the class inheritance Foo, Foo is not defined.
5 Class expression
As with functions, a class can also be defined in the form of an expression.
Const MYCLASS = Class Me {
getclassname () {return
me.name;
}
};
The above code defines a class using an expression. Note that the name of this class is MyClass rather than me, and me is only available within the class's internal code, referring to the current class.
Let inst = new MyClass ();
Inst.getclassname ()//Me
Me.Name//REFERENCEERROR:ME is not defined
The code above indicates that me is only defined within the Class.
If the inside of the class is useless, you can omit me, which means you can write the following form.
Const MYCLASS = class {/* ... */};
Class expression is used to write the immediately executing class.
Let person = new Class {
constructor (name) {
this.name = name;
}
Sayname () {
console.log (this.name);
}
} (' John ');
Person.sayname (); "John"
In the code above, person is an instance of a class that executes immediately.
6 Private methods
Private methods are common requirements, but ES6 are not provided and can only be simulated by workaround.
One approach is to distinguish names.
Class Widget {
// public method
Foo (baz) {
this._bar (baz);
} Private Method
_bar (Baz) {return
This.snaf = baz;
}
// ...
}
In the code above, the underscore in front of the _bar method indicates that this is a private method that is limited to internal use. However, this name is not insured, and can be invoked on the outside of the class.
Another approach is simply to move the private method out of the module, because all the methods inside the module are externally visible.
Class Widget {
foo (baz) {
Bar.call (this, Baz);
}
// ...
}
function Bar (Baz) {return
This.snaf = baz;
}
In the code above, Foo is a public method, and the Bar.call (this, Baz) is called internally. This allows bar to actually become the private method of the current module.
Another approach is to use the uniqueness of the symbol value to name the private method as a symbol value.
Const BAR = Symbol (' bar ');
Const SNAF = Symbol (' Snaf ');
Export Default class MyClass {
// public method
Foo (baz) {
This[bar] (baz);
} Private Method
[bar] (Baz) {return
This[snaf] = baz;
}
// ...
};
In the code above, bar and SNAF are symbol values that cause third parties to not get them, thus achieving the effects of private methods and private properties.
7 The point of this
If this is included within the method of the class, it defaults to the instance of the class. However, you must be very careful that once you use this method alone, you are likely to make an error.
Class Logger {
printname (name = ' there ') {
this.print (' Hello ${name} ');
}
Print (text) {
console.log (text);
}
}
Const LOGGER = new Logger ();
const {
printname
} = logger;
Printname (); Typeerror:cannot Read Property ' print ' of undefined
In the code above, this in the Printname method, by default, points to an instance of the Logger class. However, if you extract this method for use alone, this will point to the environment in which the method is run, because the Print method cannot be found and results in an error.
A simpler workaround is to bind this in the constructor so that the print method cannot be found.
Class Logger {
constructor () {
this.printname = This.printName.bind (this);
}
// ...
}
Another workaround is to use the arrow functions.
class Logger {
constructor () {
This.printname = (name = ' there ') => {
this.print (' Hello ${name} '); c10/>};
}
// ...
}
Another workaround is to use proxy to automatically bind this when obtaining the method.
function Selfish (target) {
Const cache = new Weakmap ();
Const Handler = {Get
(target, key) {
Const VALUE = Reflect.get (target, key);
if (typeof value!== ' function ') {return
value;
}
if (!cache.has (value)) {
Cache.set (value, Value.bind (target));
}
return Cache.get (value);
}
;
Const PROXY = new Proxy (target, handler);
return proxy;
Const LOGGER = selfish (new logger ());
8 Strict mode
Inside the class and module, the default is strict mode, so you do not need to specify the run mode using use Strict. As long as your code is written in a class or module, only strict mode is available.
Considering all the code in the future, it is actually running in the module, so ES6 actually upgraded the entire language to a strict mode.
9 Name Property
Because essentially, ES6 classes are just a layer of ES5 constructors, many of the features of a function are inherited by class, including the name attribute.
Class Point {}
point.name//' point '
point.name//"point"
The Name property always returns the name of the class immediately following the Class keyword.