Originally published in: Holmeshe. me, this article is a Chinese remake.

This series is serialized simultaneously on Medium and Nuggets.

I remember doing a lot of crap with Ajax early on and being impressed by JS as “very weird”. Recently CHANGED a job, the working language is JS. And then I found that this language is really amazing, both front and back, basically become a synonym for full stack. So this is a good opportunity to learn the language systematically. Because it’s for programmers, this series won’t cover basic “if-else”, looping, or object orientation. Instead, I’ll focus on the differences and hopefully give you a code-walking learning experience in the Pull Request!

The prototype, copy version of OOP

Prototype is a singleton template that the JS engine creates for each class at runtime. Objects of that class are created by making a copy of this template in memory. Prototype implemented OOP in an unconventional way, and I’m calling it a clone to mean it’s different, not in any derogatory way.

Let’s see how different prototype looks:

function inherits(ChildClass, ParentClass) {
  function IntermediateClass() {}
  IntermediateClass.prototype = ParentClass.prototype;
  ChildClass.prototype = new IntermediateClass;
  ChildClass.prototype.constructor = ChildClass;
  return ChildClass;
};Copy the code

This is an example of prototype-based inheritance. It doesn’t matter if you don’t understand it now, as I’ll discuss Prototype-based inheritance in more detail in the next article.

Is this useful?

As mentioned in the previous article, ES6 has defined a more standard OOP mechanism in JS. And es6-based code can be translated into ES5 syntax, so the new standard can be applied with the same compatibility as the old standard. Prototype doesn’t need to be learned. I don’t think so. ES5 still exists on a large scale in existing code. If you run this command from the Angular, React, and Vue codebases:

grep -R prototype *|wc -lCopy the code

The results were 286,405 and 756, respectively. So for me, prototype is a required course even to understand the 1,447 lines of basic code. In particular, I should note that these three frames are in alphabetical order (nervous typo, row) in order 😅.

How to play the prototype

In the following example, we first define a constructor (⬅ to my last article if you are not familiar with constructors in the JS context) and then we create objects based on this constructor to check their prototype.

In code:

var MyClass = function (){};
var obj = new MyClass;

alert(obj.__proto__ == MyClass.prototype); //=>true
alert(obj.prototype == MyClass.prototype); //=>false
// if the object's prototype does not equal to the class' prototype, what is it then
alert(obj.prototype); //=>undefined

// you can change the definition of a class on the run
MyClass.prototype.a_member = "abc";
// and the object's structure is changed as well
alert(obj.a_member); //=>abc
alert(obj.__proto__.a_member); //=>abcCopy the code

Running results:

true
false
undefined
abc
abcCopy the code

From preliminary observation, we can get the following impression:

  1. Just classes, or classesThe constructorOnly containsprototype. And thisprototypeCan be created by generating object instances__proto__To visit;
  2.  prototype__proto__It’s actually the heads and tails of a coin, and they both point to the same entity, the one described at the beginning of this articleThe singleton;
  3. If a class ofprototypeChange at run time, and the change is passed to all instances.

Further, if an instance’s __proto__ is changed at run time, the change will change the class’s prototype (class definition) upward, which in turn will cascade to update the structure of all other instances of the same type.

In code:

var MyClass = function() {}; var obj1 = new MyClass; var obj2 = new MyClass; obj1.__proto__.a_member ='abc';

// an instance can change the definition of the class
alert(MyClass.prototype.a_member); //Ooooops...
// so all other instances are affected
alert(obj2.a_member);Copy the code

Running results:

abcabcCopy the code

This is a dead end operation, because no one can stand changing class declarations. So I suggest thinking of __proto__ as a constant and not touching it.

However, if you really want to animate the definition at runtime, then animate the instance itself, because animate instances have no unspoken rules:

var MyClass = function() {}; var obj1 = new MyClass; var obj2 = new MyClass; obj1.a_member ='abc'; Alert (myclass.prototype.a_member); // alert(obj2.a_member);Copy the code

Running results:

abc
abcCopy the code

On the other hand, you can alter the class definition directly, without side effects, and just happen to have JavaScript support static member variables (or functions) :

var MyClass = function() {}; var obj1 = new MyClass; var obj2 = new MyClass; MyClass.a_member ='abc'; // alert(myclass.prototype.a_member); // alert(obj1.a_member); alert(obj2.a_member); // the member has been effectively added alert(MyClass.a_member);Copy the code

Running results:

undefined
undefined
undefined
abcCopy the code

So this can also be a divine operation, mainly because

Everything is an object

In JavaScript, everything is an object. This includes functions, constructors (classes), object instances, prototypes, __proto__, and so on. Let’s prove it in code:

var MyClass = function (){  this.a = "a";  this.b = "b"; }; var obj = new MyClass; var arry = [];function f1() {
  alert("something");
};

alert(MyClass instanceof Object);
alert(MyClass.prototype instanceof Object);
alert(MyClass.__proto__ instanceof Object);
alert(obj instanceof Object);
alert(obj.__proto__ instanceof Object);
alert(obj instanceof Object);
alert(arry instanceof Object);
alert(f1 instanceof Object);
alert(f1.prototype instanceof Object);
alert(f1.__proto__ instanceof Object);Copy the code

Running results:

true(chorus)Copy the code

Further, objects can be subdivided into first-class objects and ordinary objects. Ordinary objects are ordinary variables that can be created, modified, destroyed, or assigned to other variables at run time. The first-class object is the birkin version of the ordinary object, is unlocked membership privileges. So, in addition to being “created, modified, destroyed, or assigned to other variables,” it can also be called (as a normal function) and can create instances (as a constructor). Does this extra privilege provide another explanation for giving first-class objects a prototype? What do you think?

In code:

var MyClass = function () {
  this.a = "a";
  this.b = "b";
};

var obj = new MyClass;
function f1() {
  alert("something");
};

// MyClass is a first class object so...
alert(MyClass.prototype); // it has prototype and
alert(MyClass.__proto__); // __proto__

// obj is an object so...
alert(obj.prototype);
// it does not have prototype but
alert(obj.__proto__); // it has __proto__

// f1 is a first class object so...
alert(f1.prototype); // it has prototype and
alert(f1.__proto__); // __proto__Copy the code

Running results:

[object Object]
function () {}
undefined
[object Object]
[object Object]
function () {}Copy the code

Except…

The exception of a

Did I just say everything is an object?

var str = "whatever";
alert(str instanceof Object);
alert(str.__proto__ instanceof Object);Copy the code

Running results:

false
trueCopy the code

As you can see from the code, even though a string constant is not an object, it has a __proto__. So there are two possibilities: either strings are also objects (which they obviously are not), or everything I said above is wrong.

It’s actually true. This is due to a mechanism called autowrapping, so the basic data types are automatically wrapped as objects and the corresponding members are then called.

In code:

var str = "whatever";
alert(str.indexOf("tever"));Copy the code

The results

3Copy the code

Similarly, String constants are automatically wrapped as String() objects at run time, and then indexOf() member functions are called. This mechanism also works with other basic data types (int, float).

Exception 2

If it looks perfect, try the following:

var obj = { a:"abc", b:"bcd"};

alert(obj instanceof Object);
alert(obj.__proto__);
alert(obj.__proto__ instanceof Object);Copy the code

Running results:

true
[object Object]
falseCopy the code

Var obj and obj.__proto__ are both objects. But when I wanted to make sure, obj.__proto__ wasn’t. I feel like A blogger writing about things I don’t understand, but if you have an answer, leave a comment below. It doesn’t really matter if it doesn’t, because __proto__ is inherently nonstandard.

In the next article I will discuss one difficulty, inheritance based on the Prototype chain.

All right, that’s it for today. If you think this article is good, you can pay attention to my public number – full stack hunter.



I can also go to Medium and slap my other articles. Thanks for reading! 👋