JavaScript -- 继承与原型链
JavaScript对象有一个指向一个原型对象的链,当试图访问一个对象的属性的时候,他不仅仅会在该对象上面搜寻,还会搜寻该对象的原型,以及对象的原型的原型,依次层层搜索,直到找到名字匹配的属性或者到达原型链的末端
// 让我们假设我们有一个对象 o, 其有自己的属性 a 和 b:
// {a: 1, b: 2}
// o 的 [[Prototype]] 有属性 b 和 c:
// {b: 3, c: 4}
// 最后, o.[[Prototype]].[[Prototype]] 是 null.
// 这就是原型链的末尾,即 null,
// 根据定义,null 没有[[Prototype]].
// 综上,整个原型链如下:
// {a:1, b:2} ---> {b:3, c:4} ---> null
console.log(o.a); // 1
// a是o的自身属性吗?是的,该属性的值为1
console.log(o.b); // 2
// b是o的自身属性吗?是的,该属性的值为2
// 原型上也有一个'b'属性,但是它不会被访问到.这种情况称为"属性遮蔽 (property shadowing)"
console.log(o.c); // 4
// c是o的自身属性吗?不是,那看看原型上有没有
// c是o.[[Prototype]]的属性吗?是的,该属性的值为4
console.log(o.d); // undefined
// d是o的自身属性吗?不是,那看看原型上有没有
// d是o.[[Prototype]]的属性吗?不是,那看看它的原型上有没有
// o.[[Prototype]].[[Prototype]] 为 null,停止搜索
// 没有d属性,返回undefined
继承方法
当继承的函数被调用时,this 指向的是当前继承的对象,而不是继承的函数所在的原型对象。
var o = {
a: 2,
m: function(){
return this.a + 1;
}
};
console.log(o.m()); // 3
// 当调用 o.m 时,'this'指向了o.
var p = Object.create(o);
// p是一个继承自 o 的对象
p.a = 4; // 创建 p 的自身属性 a
console.log(p.m()); // 5
// 调用 p.m 时, 'this'指向 p.
// 又因为 p 继承 o 的 m 函数
// 此时的'this.a' 即 p.a,即 p 的自身属性 'a'
使用不同的方法来创建对象和生成原型链
语法结构创建的对象
var o = {a: 1};
// o 这个对象继承了Object.prototype上面的所有属性
// o 自身没有名为 hasOwnProperty 的属性
// hasOwnProperty 是 Object.prototype 的属性
// 因此 o 继承了 Object.prototype 的 hasOwnProperty
// Object.prototype 的原型为 null
// 原型链如下:
// o ---> Object.prototype ---> null
var a = ["yo", "whadup", "?"];
// 数组都继承于 Array.prototype
// (Array.prototype 中包含 indexOf, forEach等方法)
// 原型链如下:
// a ---> Array.prototype ---> Object.prototype ---> null
function f(){
return 2;
}
// 函数都继承于Function.prototype
// (Function.prototype 中包含 call, bind等方法)
// 原型链如下:
// f ---> Function.prototype ---> Object.prototype ---> null
构造器创建的对象
在 JavaScript 中,构造器其实就是一个普通的函数。当使用 new 操作符 来作用这个函数时,它就可以被称为构造方法(构造函数)。
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
// g是生成的对象,他的自身属性有'vertices'和'edges'.
// 在g被实例化时,g.[[Prototype]]指向了Graph.prototype.
Object.create 创建的对象
ECMAScript 5 中引入了一个新方法:Object.create()。可以调用这个方法来创建一个新对象。新对象的原型就是调用 create 方法时传入的第一个参数:
var a = {a: 1};
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (继承而来)
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty); // undefined, 因为d没有继承Object.prototype
class 关键字创建的对象
ECMAScript6 引入了一套新的关键字用来实现 class。使用基于类语言的开发人员会对这些结构感到熟悉,但它们是不同的。JavaScript 仍然基于原型。这些新的关键字包括 class, constructor,static,extends 和 super。
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
console.log(height) //2
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);
性能
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
console.log(g.hasOwnProperty('vertices'));
// true
console.log(g.hasOwnProperty('nope'));
// false
console.log(g.hasOwnProperty('addVertex'));
// false
console.log(g.__proto__.hasOwnProperty('addVertex'));
// true
hasOwnProperty 是 JavaScript 中唯一处理属性并且不会遍历原型链的方法。
因此,当你执行:
var o = new Foo();
JavaScript 实际上执行的是(或者大致这样):
var o = new Object();
o._proto_ = Foo.prototype;
Foo.call(0)
o.someProp;
它检查
o是否具有someProp属性。如果没有,它会查找
Object.getPrototypeOf(o).someProp,如果仍旧没有,它会继续查找
Object.getPrototypeOf(Object.getPrototypeOf(o)).someProp。
ps:
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)。
var proto = {};
var obj = Object.create(proto);
var a= Object.getPrototypeOf(obj)
console.log(a); {}
如果觉得还不错,请访问MDN
JavaScript -- 继承与原型链的更多相关文章
- JavaScript继承与原型链
对于那些熟悉基于类的面向对象语言(Java 或者 C++)的开发者来说,JavaScript 的语法是比较怪异的,这是由于 JavaScript 是一门动态语言,而且它没有类的概念( ES6 新增了c ...
- javascript继承之原型链(一)
function Father() { this.fatherValue = "爸爸"; } Father.prototype.getFatherValue = function ...
- JavaScript之继承(原型链)
JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...
- JavaScript中的继承(原型链)
一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...
- 对Javascript 类、原型链、继承的理解
一.序言 和其他面向对象的语言(如Java)不同,Javascript语言对类的实现和继承的实现没有标准的定义,而是将这些交给了程序员,让程序员更加灵活地(当然刚开始也更加头疼)去定义类,实现继承 ...
- 一篇JavaScript技术栈带你了解继承和原型链
作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...
- 关于JavaScript的原型继承与原型链
在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性. 这样一来,每个实例都有自己的实例属性 ...
- 图解JavaScript中的原型链
转自:http://www.jianshu.com/p/a81692ad5b5d typeof obj 和 obj instanceof Type 在JavaScript中,我们经常用typeof o ...
- JavaScript进阶之原型链
对象 function f1(){ }; typeof f1 //"function"函数对象 var o1 = new f1(); typeof o1 //"objec ...
随机推荐
- ORACLE_FUNCTION
FUNCTION: DEFINE:函数一般用于计算和返回一个值,可以将经常需要使用的计算或功能写成一个函数. 1.basic syntax create [or replace] function f ...
- python中的 if __name__ == “__main__”: 有什么用
https://stackoverflow.com/questions/419163/what-does-if-name-main-do# 问题: What does if name == " ...
- tensorflow ImportError: libmklml_intel.so: cannot open shared object file: No such file or directory
通过whl文件安装 tensorflow,显示缺少libmklml_intel.so 需要 1)安装intel MKL库 https://software.intel.com/en-us/articl ...
- NO.001-2018.02.06《木兰花·拟古决绝词柬友》清代:纳兰性德
木兰花·拟古决绝词柬友原文.翻译及赏析_纳兰性德_古诗文网 木兰花·拟古决绝词柬友 清代:纳兰性德 人生若只如初见,何事秋风悲画扇.与意中人相处应当总像刚刚相识的时候,是那样地甜蜜,那样地温馨,那 ...
- 失去光标display=none事件的坑
1.实现效果: 失去光标进行判断,如果内容为空出现提示. 2.页面代码: <tr class="tableform_tr"> <td width="15 ...
- 统计一段文章的单词频率,取出频率最高的5个单词和个数(python)
练习题:统计一段英语文章的单词频率,取出频率最高的5个单词和个数(用python实现) 先全部转为小写再判定 lower() 怎么判定单词? 1 不是字母的特殊字符作为分隔符分割字符串 (避免特殊字符 ...
- ftp免交互上传文件脚本
ftp -i -n <<! open .x.x.x user yourFtpAccount yourPasswd cd /root/DailyBuild/webapps/ delete x ...
- Ubuntu下Qt(Retex)无法输入中文
这个问题从我第一次在Ubuntu上使用Qt便困扰着我,奈何之前一直没认真去解决掉这个问题.今天作死想想,这个不可能解决不掉的.因为那么多人用Ubuntu,而且又那么多人用Qt的产品,比如Retext. ...
- [转]Ubuntu 小企鹅输入法fcitx 支持 五笔拼音
之前在Ubuntu下使用ibus五笔输入法,用了一段时间发现五笔输入法不能输入词组,并且五笔不支持拼音的功能,从网上找到可以使用fcitx替换掉ibus,因此自已尝试了一把,安装步骤如下: 1. 安装 ...
- react中性能优化的点
react提升代码性能的点 1.绑定如果改变作用域点话放在constructor里面做,这样可以保证整个程序的作用域绑定操作只会执行一次,而且避免子组件的无谓渲染. 2.内置的setState是个异步 ...