JavaScript原型,原型链

问题:什么是js原型?

js每声明一个function,都有prototype原型,prototype原型是函数的一个默认属性,在函数的创建过程中由js编译器自动添加。

也就是说:当生产一个function对象的时候,就有一个原型prototype。

举个例子:

JavaScript原型,原型链

是不是还看到了一个_proto_的属性?!骚年,你的眼睛不错~待会在解释prototype和_proto_的基友关系!

prototype的属性值是一个对象,是属性的集合,是属性的集合,是属性的集合,重要事情说三遍!

为什么要说他的属性的集合呢?我再来举个例子~:

function Person(name,age){
    this.name=name;
    this.age=age;
}
    Person.prototype.sayHello=function(){
    alert("使用原型得到Name:"+this.name);
}
var per=new Person("alin",21);
per.sayHello(); //输出:使用原型得到Name:alin

在函数Person里面自定义了属性name和age,而prototype是我们的属性集合,也就是说,我要添加sayHello这个属性到Person,则要这样写:Person.prototype.sayHello,就能添加Person的属性。

(我们可以简单的把prototype看做是一个模板,新创建的自定义对象都是这个模板prototype的一个拷贝,其实准确来说,不应该说是一个拷贝,而是一个连接,只不过这种链接是不可见,新实例化的对象内部有一个看不见的_Proto_指针,指向原型对象)。

使用原型来优化代码:

普通code:

function add(x,y){
  return x+y;
}
function subtract(x,y){
  return x-y;
}
console.log(add(1,3));

第一种方式用原型优化后:

var Calculator = function(){
 
};
Calculator.prototype = {
    add:function(x,y){
    return x+y;
},
subtract:function(x,y){
    return x-y;
}
};
console.log((new Calculator()).add(1,3));

第二种方式用原型优化后:

var Calculator = function () {};
Calculator.prototype = function(){
  add = function(x,y){
  return x+y;
},
subtract = function(x,y){
    return x-y;
}
return{
    add:add,
    subtract:subtract
}
}();
 
console.log((new Calculator()).add(1,3));   

它目的:封装私有的function,通过return的形式暴露出简单的使用名称,以达到public/private的效果。
 
------------------------------------华丽的分割线------------------------------------

js原型链
问题:什么是原型链?
根据《JavaScript高级程序设计》P162页可以作出回答:原型链是实现继承的主要方法。其基本思想是:利用原型让一个引用类型继承另一个应用类型的属性和方法。
简单回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

JavaScript高级程序设计(第3版)高清完整PDF中文+英文+源码  下载

首先,我觉得有必要先解释一下prototype 和_proto_之间的关系。
每一个基本对象都有自己的_proto_属性,而每一个函数对象都有自己的prototype原型(函数对象也属于基本对象,所以也有_proto_),每当去定义一个prototype的时候,就相当于把该实例的__proto__指向一个结构体,那么这个被指向结构体就称为该实例的原型。 我们还是来看图吧~比较清晰:

var foo = {
      x: 10,
      y: 20
}; 

JavaScript原型,原型链

解析:当你定义一个函数对象的时候,其内部就有这样一个链表关系。声明foo对象,自带了_proto_的属性,而这个属性指向了prototype,从而实现对象的扩展(例如继承等操作)。

再看一个例子:

var a = {
      x: 10,
      calculate: function (z) {
              return this.x + this.y + z
      }
};
var b = {
        y: 20,
        __proto__: a
};
 
var c = {
        y: 30,
        __proto__: a
};
 
 
b.calculate(30); // 60 

JavaScript原型,原型链

附上另外说明:

1、一个没有继承操作的函数的_proto_都会指向Object.prototype,而Object.prototype都会指向null。

2、所以,也可以很明显知道,为何null是原型链的终端。

理解了__proto__这个属性链接指针的本质。。再来理解constructor。

prototype默认的有一个叫做constructor的属性,指向这个函数本身。
一般construtor就是我们平时对函数设置的实例化对象

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/05218a6f7a0a4bd984bb51b4cc3a2762.html