JavaScript中的原型继承

JavaScript语言是面向对象的语言, 但是它是基于原型的面向对象语言
这和C++等一些语言不同, 它实际上并没有”类”, 不能实例化”类”

原型编程的基本原则:

  1. 所有的数据都是对象
  2. 得到一个对象,并不是通过实例化类,而是找到一个对象作为原型并继承它
  3. 对象会记住它的原型
  4. 如果对象无法响应某个请求,它会把这个请求委托给自己的原型

下面就来我们就来看看JavaScript是怎样以这样的规则构建对象的

1. 所有数据都是对象

我们不能说JavaScript中所有数据都是对象, 但我们可以说绝大部分数据都是对象
除了undefined以外, number、string、boolean都可以通过基本包装类变成对象来处理
JavaScript中有一个根对象Object.prototype
对象实际上都是从这个根对象克隆来的
而Object.prototype就是它们的原型

2. 得到一个对象,不是通过实例化类,而是找到一个对象作为原型并继承它

我们要想构建一个”空”对象, 可以通过构造函数var obj = new Object()或者对象字面量var obj = {}
构建时, JavaScript引擎内部会从Object.prototype上克隆一个对象出来

3. 对象会记住它的原型

JavaScript中的原型链机制允许在原型链上逐层查找,所以每个节点都必须知道它的下一个节点
即每个对象都应该记住自己的原型
我们一直说”对象的原型”, 其实并不准确
准确的说是对象的构造器有原型
JavaScript中对象都有隐藏属性__proto__
它默认指向该对象的构造器的原型对象

4. 如果对象无法响应某个请求,它会把这个请求委托给自己的原型

当一个对象无法响应某个请求是, 它会沿着原型链把请求传递下去, 知道遇到可以处理请求的对象为止
虽然JavaScript的对象那个最初都是由Object.prototype对象克隆而来的, 但对象构造器的原型不仅限于Object.prototype, 而是可以动态指向其他对象
这样, 当对象a需要用到b的能了是, 可以改变对象a构造器的原型指向b
从而达到继承的效果

下面代码是我们常用的原型继承

var obj = {name: 'payen'};

var A = function(){};
A.prototype = obj;

var a = new A();
console.log(a.name);//输出payen

这段代码执行时, 引擎做了什么呢

  • 首先, 尝试比那里a中所有属性, 没找到name属性
  • “查找name属性”的请求被委托给对象a的构造器的原型, 它被__proto__记录并指向A.prototype, 而A.prototype被设置为对象obj
  • 在对象obj中找到了name属性, 返回它的值

下面是chorme浏览器控制台打印的b
JavaScript中的原型继承_第1张图片

当我们想让一个”类” 继承另一个”类”时, 可以这样做

var A = function(){};
A.prototype = {
    name: 'payen'
};


var B = function(){};
B.prototype = new A();

var b = new B();
console.log(b.name);//输出payen

我们来分析一下执行这段代码时, 引擎做了什么

  • 首先, 尝试遍历b中所有属性, 遗憾的是没找到name属性
  • “查找name属性”的请求被委托给对象b的构造器的原型, 它记录在b.__proto__中并且指向B.prototype中, 而B.prototype设置为通过new A()创建出来的对象
  • 在这个对象中依然没找到name, 于是请求被继续委托个这个对象构造器的原型A.prototype
  • 在A.prototype中找到了name属性, 返回它的值

和把B.prototype直接指向一个对象字面量相比
通过B.prototype = new A() 在原型链上多形成一层
但其实没什么区别

如果访问的不是name而是一个不存在的值, 那么请求就会被传递到Object.prototype的顶级原型依然没找到,返回undefined

下面是chorme浏览器控制台打印的b

==主页传送门==

你可能感兴趣的:(JavaScript,继承,原型)