JavaScript 原型链
2016-08-06 19:56
459 查看
君子生非异也,善假于物也。
——《荀子·劝学》
JavaScript 中关于类的继承是一个原型继承的方式,总结起来其精髓就在于“借”这个字。
JavaScript 中,对于一个对象,它所能访问的属性,不一定全是它自己的属性,也有可能是它原型的属性,甚至是原型的原型的属性……
函数的原型是一个原型对象(prototype)。
从一个函数(类)能构造出很多对象,但一个函数只有对应的一个原型。从某种意义上来说,这个原型对象也是函数的实例之一,不过这是一个特殊的实例。
假设有一个函数
对于其原型(prototype)对象
但对于一般的f实例化对象
对于这样一个基本的构造。我们可以发现,
实际上真正属于
只有
其他的,就连
实际上我们可以看到,
总结:那么现在我们可以知道在构造过程究竟发生了什么:
构造对象
原型链接
应用构造函数
这个过程也可以手动地操作一下。
这样就完成了类的继承,如果理解了最终的实例对象的寻找属性的方式,那么这种做法是显而易见的。
——《荀子·劝学》
JavaScript 中关于类的继承是一个原型继承的方式,总结起来其精髓就在于“借”这个字。
JavaScript 中,对于一个对象,它所能访问的属性,不一定全是它自己的属性,也有可能是它原型的属性,甚至是原型的原型的属性……
__proto__是一个属性,除了
null与
undefined没有以外,其他的都具有这个属性。用于指向对象的原型,是一个引用(指针)。
"123".__proto__ === String.prototype; // true (1).__proto__ === Number.prototype; // true (function A(x){return x;}).__proto__ === Function.prototype; // true
constructor 与 prototype
对象的构造器(constructor) 是一个函数。函数的原型是一个原型对象(prototype)。
从一个函数(类)能构造出很多对象,但一个函数只有对应的一个原型。从某种意义上来说,这个原型对象也是函数的实例之一,不过这是一个特殊的实例。
假设有一个函数
A
function A(){};
对于其原型(prototype)对象
obj来说,构造器就是
A
var obj = A.prototype; obj.constructor === A; // true
但对于一般的f实例化对象
x:
var x = new A(); x.hasOwnProperty('constructor'); // false x.constructor === A; // true
x是不具有
constructor属性的,但
x.constructor依然能访问,并且指向的也是
A。这是因为
x.constructor沿着原型链进行了回溯搜索,实际上
x.constructor就是
x.__proto__.constructor,而
x.__proto__就是
A.prototype。
构造过程
function A(){this.key = 1;}; A.prototype.val = 1; var x = new A();
对于这样一个基本的构造。我们可以发现,
x可访问的属性如下
x.__defineGetter__ x.__defineSetter__ x.__lookupGetter__ x.__lookupSetter__ x.__proto__ x.constructor x.hasOwnProperty x.isPrototypeOf x.propertyIsEnumerable x.toLocaleString x.toString x.valueOf x.val x.key
实际上真正属于
x自己的属性有什么呢?
只有
x.key是真正属于
x的,这两个都是在
new A()的调用过程中产生的。
其他的,就连
x.val都是属于
A.prototype而不属于
x。
x.__proto__ === A.prototype; // true x.__proto__.__proto__ === Object.prototype; // true x.__proto__.__proto__.__proto__ === null; // true x.hasOwnProperty('__proto__'); // false x.__proto__.hasOwnProperty('__proto__'); // false x.__proto__.__proto__.hasOwnProperty('__proto__'); // true
实际上我们可以看到,
x能访问的属性,除了
__proto__, key这样自身的属性之外,还有
A.prototype, Object.prototype的。
总结:那么现在我们可以知道在构造过程究竟发生了什么:
构造对象
原型链接
应用构造函数
function myNew(f) { // create new object var obj = {}; // link to prototype chain obj.__proto__ = f.prototype; // apply constructor to the object f.apply(obj, Array.prototype.slice.call(arguments, 1)); // return the object return obj; }
这个过程也可以手动地操作一下。
function f() { this.key = 1; }; f.prototype.val = 2; var x = {}; x instanceof f; // false x.val; // undefined x.key; // undefined x.__proto__ = f.prototype; x instanceof f; // true x.val; // 2 x.key; // undefined f.call(x); // same as f.apply(x, []); x instanceof f; // true x.val; // 2 x.key; // 1
原型继承
类的继承其实很简单:function A(){}; function B(){}; // B inherits A B.prototype.__proto__ = A.prototype;
这样就完成了类的继承,如果理解了最终的实例对象的寻找属性的方式,那么这种做法是显而易见的。
相关文章推荐
- JavaScript_类、构造函数和原型;
- JavaScript 中原型继承(prototype-based inheritance)的原理
- 深入理解javascript原型和闭包(5)——instanceof
- JavaScript探秘:强大的原型和原型链
- JavaScript原型与原型链学习笔记
- 理解JavaScript的原型和闭包
- 深刻理解JavaScript基于原型的面向对象
- Javascript 原型和原型链
- JavaScript使用原型和原型链实现对象继承的方法详解
- JavaScript 原型链学习总结
- 理解javascript原型和作用域系列(8)——简述【执行上下文】
- 深入理解javascript原型链和继承
- javascript中继承(一)-----原型链继承的个人理解
- 深入理解javascript原型链和继承
- 简单分析javascript面向对象与原型
- 深入理解javascript原型和闭包(11)——执行上下文栈
- javascript原型和闭包(15)——闭包
- 深入理解javascript原型和闭包(3)——prototype原型
- JavaScript面向对象-原型的内存模型
- javascript 原型链等疑难答案