var s = 'hello world'; alert(typeof s); // string
alert (s == window.s); // true alert (typeof window); // object
alert(s.length); // 11 ( )
var s = 'futurico'; // s window (window.s) var f = function(){ // f window (window.f) alert(this == window); // true alert(this.s); // 'futurico' } f(); // f window (window.f()) var o = {}; // o window (window.o) os = 'karaboz'; // s window.o (window.os) of = function(){ // f window.o (window.of) alert(this == o); // true alert(this.s); // 'karaboz' } of(); // f window.o (window.of())
new
. The constructor function provides the same features as a class in other programming languages: namely, it describes the template by which objects (instances) of the class will be created. The basis of such a template is the enumeration of properties and methods that an object created on the basis of this class will possess. For all built-in data types in JavaScript, there are built-in function constructors. var str='karaboz';
var str = new String('karaboz');
String
. // var num = 12345.6789; // var num = new Number(12345.6789); // var bul = true; // var c = new Boolean(true); // var fun = function(x){var p = x}; // var fun = new Function('x', 'var p = x'); // var arr = ['a', 'b', 'c']; // var arr = new Array('a', 'b', 'c'); // var obj = {}; // var obj = new Object();
alert(num.toFixed(1)); // 12345.6 alert(arr.length); // 3
String
): var str1 = 'karaboz'; var str2 = new String('karaboz'); alert(str1 == str2); // true
str1.tell = function(){ alert(this); } str1.tell(); // 'str1.tell is not a function'
str2.tell = function(){ alert(this); } str2.tell(); // 'karaboz'
var s = 'futurico'; // s window (window.s) var f = function(){ // f window (window.f) alert(this == window); // true alert(this.s); // 'futurico' } f(); // f window (window.f()) fs = 'karaboz'; // s window.f (window.fs) fm = function(){ // m window.f (window.fm) alert(this == f); // true alert(this.s); // 'karaboz' } fm(); // m window.f (window.fm())
// - - var Class = function(p){ alert('My name is constructor'); this.p = p; }
var o = new Class('karaboz'); alert(o); // [Object object] alert(op); // 'karaboz' - o
var o = Class('karaboz'); // window.Class() alert(o); // undefined, , Class() alert(window.p); // 'karaboz' - window
.prototype
property for it. Any properties and methods recorded in the .prototype
function will be available as properties and methods of objects created on the basis of this function. This is the basis for the description of the template (class), according to which the objects will be created. Class.prototype.method = function(){ alert('my name is .method'); }
o.method(); // !
.prototype
function that created the object..constructor
, which points to the constructor function that created this object: alert(o.constructor == Class); // true
.constructor
property in the object, takes it from the .prototype of the constructor function that created the object. Check: alert(Class.prototype.constructor == Class); // true
.prototype
exists only for the constructor function, but not for the object itself created on its basis: alert(o.prototype); // undefined alert(o.constructor.prototype); // [Object object]
.prototype
function exists for all objects, including objects embedded in JavaScript, such as strings, numbers, etc. Moreover, there are already no restrictions in creating own properties and methods (we saw these restrictions when trying to directly assign properties and methods to a string variable - to an object created via a string literal): var s = 'karaboz'; s.constructor.prototype.tell = function(){ alert(this); } s.tell(); // , 'karaboz'
String.prototype.tell = function(){ alert(this); }
.this
inside a constructor function: var Class = function(p){ this.p = p; } var o = new Class('karaboz'); alert(op); // 'karaboz' op = 'mertas'; alert(op); // 'mertas'
.prototype
function: Class.prototype.method = function(){ alert('my name is .method'); } obj.method(); // 'my name is .method' obj.method = function(){ alert('my name is .method, but I am new one!'); } obj.method(); // 'my name is .method, but I am new one!'
.method
method to the obj
object, we do not change the method of the same name in the .prototype
function, but just close it from the interpreter, creating a new property with the same name in our object. Those. all newly created objects will still have the standard method from .prototype
..prototype
. To do this, simply delete the .method
property of the object itself: delete o.method; o.method(); // 'my name is .method'
.prototype
of the constructor function are not copied to newly created objects. All objects of this class use the reference to the same properties and methods. At the same time, we can define open members at any point of the program, including even after the creation of an object (instance) of a class. var Class = function(p){ var secret = p; var count = 3; var counter = function(){ count –; if(count > 0){ return true; } else { return false; } } }
secret
, count
and counter
properties are created in the object upon its initialization. They are called closed because they do not have access to both the code from outside the object and the public methods of the object itself. To understand how you can use these private properties, you need to refer to the preferred methods. var Class = function(p){ var secret = p; var count = 3; var counter = function(){ if(count > 0){ count –; return true; } else { return false; } } this.tellSecret = function(){ if(counter()){ return secret; } else { return null; } } } var o = new Class('12345'); alert(o.tellSecret()); // '12345' alert(o.tellSecret()); // '12345' alert(o.tellSecret()); // '12345' alert(o.tellSecret()); // null // counter, // a , o.counter = function(){ return true; } alert(o.tellSecret()); // null
.tellSecret
is the preferred method. It returns the private property secret
at the first three calls, and at all subsequent starts to return null
. Each time .tellSecret
calls the private method counter
, which itself has access to the private properties of the object. Any code has access to the .tellSecret
method, but this does not give direct access to the private members of the object..prototype
, a copy of the privileged method is created in each object that is created, which naturally entails a greater memory consumption. Private and privileged members are created only at the time of initialization of the object and later can not be changed. var Class = function(p){ this.p = p; } Class.prototype.tell = function(word){ alert(this.p + ' ' + word + ' ' + this.constructor.p); // alert(this.p + ' ' + word + ' ' + Class.p); } Class.p = 'futurico'; var o = new Class('karaboz'); o.tell('love'); // 'karaboz loves futurico';
function
operator, we always create not a function, but a closure. A closure “remembers” the values ​​of all variables that existed in the context creating this closure, even when the function is used already outside the context that created it. var createFunc = function(param){ var closureParam = param; // var returnedFunc = function(){alert(closureParam);} return returnedFunc; } var f = createFunc('karaboz');
f
, we will see that this is a normal function, in the body of which is the closureParam
parameter, which is undefined anywhere in the surrounding context and should give an error: alert(f); // : function(){alert(closureParam);}
function(){alert(closureParam);}
due to the closure effect, remembers closureParam
from the context that generated it: f(); // 'karaboz'
.tellSecret
method described above, now we can understand how it works. The method remembers both the private function count()
and the private property secret
, declared in the context that creates .tellSecret
. At the same time, when count()
is called inside .tellSecret
, this last function, in turn, remembers the count()
.tellSecret
used in its body..prototype
property: when the object method is called, the interpreter searches for this method in the properties of the object itself, and if it does not find the method there, it continues searching in the property (object) of the object's .prototype
function. var Class = function(){ // - this.className = 'Class'; } Class.prototype.method = function(){ // alert('method of ' + this.className); } var ClassSub = function(){ // - this.className = 'ClassSub'; } ClassSub.prototype = new Class(); // .prototype var objSub = new ClassSub(); // ClassSub objSub.method(); // ! 'method of ClassSub'
.method
its superclass (executes it as its own). How does this happen? First, the interpreter searches for the .method
method in the objSub
object objSub
and naturally does not find it there. Next, the interpreter accesses ClassSub.prototype
and searches for .method
among the properties of this object. Again, it doesn’t find anything: we have never set anything similar to ClassSub.prototype.method = function(){}
. But after all, the ClassSub.prototype
object ClassSub.prototype
created from the Class()
constructor function. Therefore, not finding the necessary properties in ClassSub.prototype
itself, the interpreter refers to the .prototype
function of the constructor of this object. And here already finds the requested method: Class.prototype.method = function(){}
. // .method objSub .method ClassSub.prototype alert(objSub.method == ClassSub.prototype.method); // true // .method ClassSub.prototype .method Class.prototype alert(ClassSub.prototype.method == Class.prototype.method); // true
Object
. If in the Object.prototype
it still does not find the requested method, it will return an error. The Object
class lies at the very top of any possible hierarchy of classes created in JavaScript. ClassSub.prototype.method = function(){ // alert('method of ' + this.className + ' but new one'); } ClassSub.prototype.methodSub = function(){ // alert('methodSub of ' + this.className); }; // objSub.method(); // 'method of ClassSub but new one' // objSub.methodSub(); // 'methodSub of ClassSub' var obj = new Class(); // Class // obj.method(); // 'method of Class' // obj.methodSub(); // 'obj.methodSub is not a function'
Animal
class in which the name of an individual will be passed as a parameter, and each new instance of which will scream at birth (= var Animal = function(name){ this.name = name; this.cry(); // } Animal.prototype.cry = function(){ alert('whoa!'); } var animal_thing = new Animal('karaboz'); // 'whoa!';
var Cat = function(name){ this.name = name; this.cry(); } Cat.prototype = new Animal(); // Animal Cat.prototype.cry = function(){ // .cry alert('meow!'); } var cat_thing = new Cat('mertas');
Animal
, but just point out the equality of the prototypes of the two classes? (after all, it is through their prototypes that they are connected). Let's try to change this line: Cat.prototype = Animal.prototype;
Animal
superclass right after creating an instance of the Cat
subclass. var animal_thing_new = new Animal('juks'); // 'meow!', Cat!
Cat.prototype = Animal.prototype
, we pass the Animal.prototype object to the Cat.prototype object by reference (as always happens when an object is assigned to a variable).Therefore, any changes of the first reasonably lead to a change in the second. When we wrote Cat.prototype = new Animal()
, we created a Cat.prototype
new object. Changing its properties, we did not affect the properties of .prototype
the object's constructor function itself..prototype
all the properties and methods from the .prototype
superclass to the subclass. Rewrite the problem line as follows: for (var prop in Animal.prototype){ Cat.prototype[prop] = Animal.prototype[prop]; }
.prototype
a new object in the subclass that has a link to the .prototype
superclass, but does not launch the constructor function of the superclass. Rewrite the complex line again: var Empty = function(){}; // - Empty.prototype = Animal.prototype; Cat.prototype = new Empty();
Cat.prototype
an object in an artificial class Empty
. When creating this object, nothing happens because the constructor function is Empty()
empty. Any assignments in Cat.prototype
will affect only changes in the properties of the object itself Cat.prototype
and will not affect the constructor function of the superclass Animal
. If the interpreter does not find the required method either in the class instance Cat
or in the properties Cat.prototype
, it will turn to the object's constructor function Cat.prototype (== new Empty())
and begin to search in Empty.prototype
, which refers directly to the one we need.Animal.prototype
var Cat = function(name){ Animal.apply(this, arguments); }
Cat
call the constructor function of the superclass Animal
in the context of the object new Cat()
. In principle, our code already works well, but I would like to see it more universal - not tied to specific class names..constructor
, taken from .prototype.constructor
the constructor function that spawned it. However, when we recorded:, Cat.prototype = new Empty()
we created a Cat.prototype
new object. If you now try to turn to (new Cat()).constructor
, the interpreter will go to look for it in Cat.prototype.constructor
, which means in (new Empty().constructor)
and will find this property as a result in Empty.prototype.constructor ( == Animal.prototype.constructor)
. Those.our property .constructor
now points to the constructor function of a superclass, not a subclass! We have corrupted this property. Knowing all this, right now could be written: var Cat = function(name){ this.constructor.apply(this, arguments); }
.constructor
an object must point to a construct function of a subclass, not a superclass. Therefore, let's look like this: in the place of the last problem line in which inheritance took place, we write the following: var Empty = function(){}; // - Empty.prototype = Animal.prototype; Cat.prototype = new Empty(); Cat.prototype.constructor = Cat; // - Cat.superClass = Animal; // - , - : var Cat = function(name){ Cat.superClass.apply(this, arguments); }
Cat.prototype.cry = function(){ Cat.superClass.prototype.cry.apply(this, arguments); alert('one more cat was born'); }
.prototype
built-in constructor function Function
. Thus, we will create a new method for all possible functions, incl. and for our custom classes. // Function.prototype.inheritsFrom = function(superClass) { var Inheritance = function(){}; Inheritance.prototype = superClass.prototype; this.prototype = new Inheritance(); this.prototype.constructor = this; this.superClass = superClass; } // - var Class = function(){} // Class.prototype.method = function(){}; // - var ClassSub = function(){ ClassSub.superClass.apply(this, arguments); } // ClassSub.inheritsFrom(Class); // sic! // ClassSub.prototype.method = function(){ ClassSub.superClass.prototype.method.apply(this, arguments); }
Source: https://habr.com/ru/post/15444/
All Articles