Prototype is a part of the notes in JavaScript that is difficult to understand. Here we will explain the prototype in JS through several key knowledge points. Please see details below for specific content.
1 Prototype Design Pattern
You can use clone() to implement the prototype method in .Net
The main idea of the prototype method is that there is now a class A, and I want to create a class B. This class is based on A and can be extended. We call the prototype of B A.
2 JavaScript methods can be divided into three categories:
a class method
b Object method
c prototype method
Example:
function People(name) { this.name=name; //对象方法 this.Introduce=function(){ alert("My name is "+this.name); } } //类方法 People.Run=function(){ alert("I can run"); } //原型方法 People.prototype.IntroduceChinese=function(){ alert("我的名字是"+this.name); } //测试 var p1=new People("Windking"); p1.Introduce(); People.Run(); p1.IntroduceChinese();
3 obj1.func.call(obj) method
It means treating obj as obj1 and calling the func method
Okay, let’s solve the problems one by one:
What does prototype mean?
Every object in JavaScript has a prototype attribute. The explanation of the prototype attribute of an object in Javascript is: return a reference to the prototype of the object type.
A.prototype = new B();
Understanding prototype should not be confused with inheritance. The prototype of A is an instance of B. It can be understood that A has cloned all the methods and properties in B. A can use B's methods and properties. The emphasis here is on cloning rather than inheritance. This situation can occur: A's prototype is an instance of B, and B's prototype is also an instance of A.
Let’s look at an experimental example:
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); // 显示baseClass::showMsg
We first define the baseClass class, and then we define extentClass, but we plan to use an instance of baseClass as the prototype, and the extendedClass to be cloned also contains the showMsg object method.
extendClass.prototype = new baseClass() can be read as: extendClass is created by cloning an instance of baseClass as the prototype.
Then there will be a question, what if extendClass itself contains a method with the same name as the method of baseClass?
The following is extended experiment 2:
function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg();//显示extendClass::showMsg
Experimental proof: When the function is running, it will first look for the function in the ontology. If it is found, it will be run. If it cannot be found, it will look for the function in the prototype. Or it can be understood that the prototype will not clone the function with the same name.
Then there will be a new question:
What if I want to use an instance of extendClass to call the object method showMsg of baseClass?
The answer is to use call:
extendClass.prototype = new baseClass(); var instance = new extendClass(); var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg
The baseinstance.showMsg.call(instance); here reads as "Call the instance as baseinstance and call its object method showMsg"
Okay, someone here may ask, why not use baseClass.showMsg.call(instance);
This is the difference between object methods and class methods. What we want to call is the object method of baseClass
Finally, if you understand the following code clearly, then you can understand what this article says:
<script type="text/javascript"> function baseClass() { this.showMsg = function() { alert("baseClass::showMsg"); } this.baseShowMsg = function() { alert("baseClass::baseShowMsg"); } } baseClass.showMsg = function() { alert("baseClass::showMsg static"); } function extendClass() { this.showMsg =function () { alert("extendClass::showMsg"); } } extendClass.showMsg = function() { alert("extendClass::showMsg static") } extendClass.prototype = new baseClass(); var instance = new extendClass(); instance.showMsg(); //显示extendClass::showMsg instance.baseShowMsg(); //显示baseClass::baseShowMsg instance.showMsg(); //显示extendClass::showMsg baseClass.showMsg.call(instance);//显示baseClass::showMsg static var baseinstance = new baseClass(); baseinstance.showMsg.call(instance);//显示baseClass::showMsg </script>
ps: js Prototype attribute explanation and common methods
Function: Prototype
Each constructor has an attribute called prototype (prototype, which will not be translated below, use its original text). This attribute is very useful for declaring common variables or functions for a specific class.
Definition of prototype
You don’t need to explicitly declare a prototype attribute because it exists in every constructor. You can take a look at the following example:
Example PT1
CODE:
function Test() { } alert(Test.prototype); // 输出 "Object"
Add attributes to prototype
As you can see above, prototype is an object, therefore, you can add properties to it. Properties you add to the prototype will become common properties to objects created using this constructor.
For example, I have a data type Fish below, and I want all fish to have these attributes: livesIn="water" and price=20; in order to achieve this, I can add those attributes to the prototype of the constructor Fish.
Example PT2
CODE:
function Fish(name, color) { this.name=name; this.color=color; } Fish.prototype.livesIn="water"; Fish.prototype.price=20;
Let’s make some fish next:
CODE:
var fish1=new Fish("mackarel", "gray"); var fish2=new Fish("goldfish", "orange"); var fish3=new Fish("salmon", "white");
Let’s take a look at the attributes of fish:
CODE:
for (int i=1; i<=3; i++) { var fish=eval_r("fish"+i); // 我只是取得指向这条鱼的指针 alert(fish.name+","+fish.color+","+fish.livesIn+","+fish.price); }
The output should be:
CODE:
"mackarel, gray, water, 20" "goldfish, orange, water, 20" "salmon, white water, 20"
你看到所有的鱼都有属性livesIn和price,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。
你也可以通过prototype来给所有对象添加共用的函数。这有一个好处:你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点,让我们重新来看Example DT9并使用prototype来重写它:
用prototype给对象添加函数
Example PT3
CODE:
function Employee(name, salary) { this.name=name; this.salary=salary; } Employee.prototype.getSalary=function getSalaryFunction() { return this.salary; } Employee.prototype.addSalary=function addSalaryFunction(addition) { this.salary=this.salary+addition; }
我们可以象通常那样创建对象:
CODE:
var boss1=new Employee("Joan", 200000); var boss2=new Employee("Kim", 100000); var boss3=new Employee("Sam", 150000);
并验证它:
CODE:
alert(boss1.getSalary()); // 输出 200000 alert(boss2.getSalary()); // 输出 100000 alert(boss3.getSalary()); // 输出 150000
这里有一个图示来说明prototype是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做__proto__,这个属性指向了它的构造器(Employee)的属性prototype。当你执行 getSalary或者addSalary的时候,这个对象会在它的__proto__找到并执行这个代码。注意这点:这里并没有代码的复制(和 Example DT8的图表作一下对比)。