五章 原型

1、[[ Prototype ]]

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值。

对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象
的 [[Prototype]] 链:

 var anotherObject = {
a:2
};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create( anotherObject );
myObject.a; //

还有另外一种方法,就是使用for..in遍历对象时原理,和查找[[ Prototype ]]链想死,任何可以通过原型链访问到的属性都会被枚举。使用in操作符来检查属性在对象中是否存在也会查找对象的整条原型链(无论属性是否可枚举)

var anotherObject = {
a:2
};
// 创建一个关联到 anotherObject 的对象
var myObject = Object.create( anotherObject );
for (var k in myObject) {
console.log("found: " + k);
}
// found: a
("a" in myObject); // true

2、“构造函数“

在 JavaScript 中对于“构造函数”最准确的解释是,所有带 new 的函数调用。函数不是构造函数,但是当且仅当使用 new 时,函数调用会变成“构造函数调用”

 function NothingSpecial() {
console.log( "Don't mind me!" );
}
var a = new NothingSpecial();
// "Don't mind me!"
a; // {}

3、原型继承【重点】

图中由下到上的箭头表明这是委托关联,不是复制操作。

典型的“原型风格”,例子如下:

 function Foo(name) {
this.name = name;
}
Foo.prototype.myName = function() {
return this.name;
};
function Bar(name,label) {
Foo.call( this, name );
this.label = label;
}
// 我们创建了一个新的 Bar.prototype 对象并关联到 Foo.prototype
Bar.prototype = Object.create( Foo.prototype );
// 注意!现在没有 Bar.prototype.constructor 了
// 如果你需要这个属性的话可能需要手动修复一下它
Bar.prototype.myLabel = function() {
return this.label;
};
var a = new Bar( "a", "obj a" );
a.myName(); // "a"
a.myLabel(); // "obj a"

核心部分就是语句 Bar.prototype = Object.create( Foo.prototype ) 。调用Object.create(..) 会凭空创建一个“新”对象并把新对象内部的 [[Prototype]] 关联到你指定的对象(本例中是 Foo.prototype )。但是 Object.create(..)唯一的缺点就是需要创建一个新对象然后把旧对象抛弃掉,不能直接修改已有的默认对象。

ES6添加了一个辅助函数Object.setPrototypeOf(..) ,可以用标准并且可靠的方法来修改关联。

对比一下两种关联的方法

 // ES6 之前需要抛弃默认的 Bar.prototype
Bar.ptototype = Object.create( Foo.prototype );
// ES6 开始可以直接修改现有的 Bar.prototype
Object.setPrototypeOf( Bar.prototype, Foo.prototype );

4、检查“类”的关系

寻找对象a委托的对象,也就是检查一个实例(js中的对象)的继承祖先(js中的委托关联)被称为内省(或者反射)

例子

 function Foo() {
// ...
}
Foo.prototype.blah = ...;
var a = new Foo();

方法一  (instanceof)

instanceof 操作符的左操作数是一个普通的对象,右操作数是一个函数。 instanceof 回答的问题是:在 a 的整条 [[Prototype]] 链中是否有指向 Foo.prototype 的对象?可是,这个方法只能处理对象( a )和函数(带 .prototype 引用的 Foo )之间的关系。如果你想判断两个对象(比如 a 和 b )之间是否通过 [[Prototype]] 链关联,只用 instanceof无法实现

a instanceof Foo; // true

方法二

在本例中,我们实际上并不关心(甚至不需要) Foo ,我们只需要一个可以用来判断的对象(本例中是 Foo.prototype )就行。 isPrototypeOf(..) 回答的问题是:在 a 的整条 [[Prototype]] 链中是否出现过 Foo.prototype ?

Foo.prototype.isPrototypeOf( a ); // true

 5、创建关联

Object.create() 的polyfill代码。这段 polyfill 代码使用了一个一次性函数 F ,我们通过改写它的 .prototype 属性使其指向想要关联的对象,然后再使用 new F() 来构造一个新对象进行关联。

 if (!Object.create) {
  Object.create = function(o) {
  function F(){}
  F.prototype = o;
  return new F();
  };
}

 第六章 行为委托

重点:对象关联

 Foo = {
init:function(who){
this.me=who;
},
identify:function(){
return "i am "+this.me;
}
};
Bar = Object.create(Foo);
Bar.speak = function(){
console.log("hello"+this.identify()+".");
}
var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");
b1.speak();
b2.speak();

ES6 使用更好的对象字面形式的语法和简洁方法

 var AuthController = {
errors: [],
checkAuth() {
// ...
},
server(url,data) {
// ...
}
// ...
};
// 现在把 AuthController 关联到 LoginController
Object.setPrototypeOf( AuthController, LoginController );

你不知道的JavaScript(上)this和对象原型(四)原型的更多相关文章

  1. 读书笔记-你不知道的JavaScript(上)

    本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...

  2. 【JavaScript】类继承(对象冒充)和原型继承__深入理解原型和原型链

    JavaScript里的继承方式在很多书上分了很多类型和实现方式,大体上就是两种:类继承(对象冒充)和原型继承. 类继承(对象冒充):在函数内部定义自身的属性的方法,子类继承时,用call或apply ...

  3. JavaScript(2)——对象属性、原型与原型链

    对象属性.原型与原型链 哈哈哈,我的第二篇博客哟,说的是对象属性.原型与原型链.可能这些只是某些小点串联起来的,逻辑性没有很强.所以会对文章的可读性和理解性带来一些困扰.不过,今天我又前进了那么一小步 ...

  4. 《你不知道的Javascript》感悟篇—对象属性遍历的那些事

    划重点 本篇笔者将重点介绍JavaScript中 getOwnPropertyNames .Object.keys.for ... in 的使用及他们之间的异同点. getOwnPropertyNam ...

  5. 《你不知道的javascript(上)》笔记

    作用域是什么 编译原理 分词/词法分析 这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元 解析/语法分析 词法单元流(数组)转换成一个由元素逐级嵌套所组成 ...

  6. JavaScript -基础- 函数与对象(四) BOM 对象

    一.BOM对象 BOM游览器对象模型,可以与游览器对话 BOM下Window对象最重要,还有history.location对象 二.Window对象方法 1.alert提示框 2.confirm c ...

  7. JavaScript中的对象与原型—你不知道的JavaScript上卷读书笔记(四)

    一.对象 对象可以通过两种形式定义:声明(文字)形式和构造形式.即: var myObj = { key: value // ... }; 或: var myObj = new Object(); m ...

  8. 《你不知道的JavaScript》整理(三)——对象

    一.语法 两种形式定义:文字形式和构造形式. //文字形式 var myObj = { key: value }; //构造形式 var myObj = new Object(); myObj.key ...

  9. javascript面向对象系列第一篇——构造函数和原型对象

    × 目录 [1]构造函数 [2]原型对象 [3]总结 前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如 ...

  10. javascript中的对象,原型,原型链和面向对象

    一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...

随机推荐

  1. C#读写XML的两种一般方式

    针对XML文档的应用编程接口中,一般有两种模型:W3C制定的DOM(Document Object Method,文档对象模型)和流模型. 流模型的两种变体:"推"模型(XML的简 ...

  2. Java第09次实验(IO流)-实验报告

    0. 字节流与二进制文件 使用DataOutputStream与FileOutputStream将Student对象写入二进制文件student.data 二进制文件与文本文件的区别 try...ca ...

  3. 性能测试:深入理解线程数,并发量,TPS,看这一篇就够了

    并发数,线程数,吞吐量,每秒事务数(TPS)都是性能测试领域非常关键的数据和指标. 那么他们之间究竟是怎样的一个对应关系和内在联系? 测试时,我们经常容易将线程数等同于表述为并发数,这一表述正确吗? ...

  4. oracle插入,更新,删除数据

    插入,更新,删除数据 oracle提供了功能丰富的数据库管理语句 包括有效的向数据库中插入数据的insert语句 更新数据的update语句 以及当数据不再使用时删除数据的delete语句 更改数据之 ...

  5. Django2.0--创建缓存表

    创建缓存表 在项目的虚拟环境下(若有),执行:python manage.py createcachetab

  6. 【Luogu 1993】差分约束系统问题——小K的农场

    Luogu P1993 前置知识:最短路径相关算法 如果一个系统由n个变量和m个约束条件组成,形成m个形如ai-aj≤k的不等式(i,j∈[1,n],k为常数),则称其为差分约束系统. 显然题目中给出 ...

  7. 《手把手教你》系列练习篇之5-python+ selenium自动化测试(详细教程)

    1.  简介 今天我们继续前边的练习,学习和练习一下:如何使用webdriver方法获取操作复选框-CheckBox.测试不同的分辨率.如何断言title.如何获取某一个元素的text属性值等等,这些 ...

  8. flask实现验证码并验证

    效果图: 点击图片.刷新页面.输入错误点击登录时都刷新验证码 实现步骤: 第一步:先定义获取验证码的接口 verificationCode.py #验证码 @api.route('/imgCode') ...

  9. Idea创建maven项目,报错xxx already exists in VFS

    1.问题描述: 我打算在父级maven项目中创建子级project,但是一直报错如下: 2.stackover flow中找到了问题的答案, 地址:https://stackoverflow.com/ ...

  10. Java标识符(Identifier)(关键字和保留字)

    Java标识符(Identifier) 1. 只能由英文字母(A~Z)或(a~z).下划线(_).美元符号($)和数字(0~9)组成,且开头不能为数字. 2. 区分大小写! 3. 无长度限制! _3_ ...