prototype的本质
在《关于思维方式的思绪》那篇文章里提到了,
原型的本质就是一种委托关系。
即我这里没有,就到我的原型里去看看,一旦找到就当成我的用。
本文详细说一下这个事情。
比如某女买东西,钱都是她老公付款的。
用程序刻画是这样的:
var girl = {
name:'小美'
};
var boy = {
name:'小帅',
pay:function(){
console.log('花了1000元');
}
};
Object.setPrototypeOf(girl,boy);
girl.pay();
/**
程序中指明了girl的原型是boy, girl 没有pay方法, 但是boy有, 所以boy花钱了.
从这个例子来看,原型是一种委托关系,如果说是一种继承关系就不是那么贴切了.
*/
var girl0 = {
name: '小美',
pay:function(){
boy0.pay();
}
}; var boy0 = {
name: '小帅',
pay:function(){
console.log('花了2000元');
}
}
girl0.pay();
同上面代码意义相同
/**
用这种委托关系,而不是用继承关系去理解原型,会感觉一切豁然开阔.
下面我们通过这个例子看看什么事原型链?
*/
var a = {
fn1:function(){
console.log(1);
}
};
var b = {
fn2:function(){
console.log(2);
}
};
var c = {
fn3:function(){
console.log(3);
}
};
var d = {
fn4:function(){
console.log(4);
}
};
Object.setPrototypeOf(d,c);
Object.setPrototypeOf(c,b);
Object.setPrototypeOf(b,a);
d.fn1();
d.fn2();
d.fn3();
d.fn4();
/**
上面代码中,a是b的原型,b是c的原型,c是d的原型.
那么d要找到fn1方法,怎么找呢?
先去其原型c中找.==没找到
再去c的原型b中找.==没找到
再去b的原型a中找.==找到了
因此能调用fn1的方法.
上面的过程就是原型链查找的过程.
讲到这里,原型链的原理想必是懂了.
此时我们再看a,b,c,d四个对象是什么关系?
如果要看作是集成的话,那么就是父子关系.
如果用委托的观点来看,那么每一个对象,都是后一个对象的智囊,也就是原型.
所以本文的关点是什么呢?
不要把原型当成亲爹,要当成智囊,要当成老公,要当成干爹.
本质是委托关系,说白了,就是利用.
其实,讲到这里原型是什么已经基本说完,后面我们准备展开说说,跟构造函数扯上.
*/
第一个问题:什么叫做"一旦找到就当我的用"?
其实指的就是this问题.
var aaa = {
sayName:function(){
console.log(this.name);
}
};
var laoyao = {
name:'laoyao'
};
Object.setPrototypeOf(laoyao,aaa);
laoyao.sayName();
第二个问题:克隆的观点?
加入一个对象是一个空对象的原型.
因为空对象什么都没有,所有的都来自其原型,我们可以认为此对象是其原型的克隆.
var laowang = {
name:'laowang',
sayName:function(){
console.log(this.name);
}
};
var fenshen={};
Object.setPrototypeOf(fenshen,laowang);
console.log(fenshen.name);
fenshen.sayName();
当然, Object.create更适合描述克隆.
var laoli = {
name:'laoli',
sayName:function(){
console.log(this.name);
}
};
var clone = Object.create(laoli);
clone.sayName();
第三:我们封装产生对象的过程?
希望上述对象通过函数产生.
var createPerson = function(name){
return{
name:name,
sayName:function(){
console.log(this.name);
}
};
}
var laozhang =createPerson('laozhang');
laozhang.sayName();
我也换种方式来做:
var createPersonOther = function(name){
var o = {};
o.name = name;
var proto ={
sayName:function(){
console.log(this.name);
}
};
Object.setPrototypeOf(o,proto);
return o;
}
var laoyang =createPersonOther('laoyang');
laoyang.sayName();
var createPerson =function(name){
var o = {};
o.name = name;
Object.setPrototypeOf(o,createPerson.proto);
return o;
}
createPerson.proto={
sayName:function(){
console.log(this.name);
}
};
var laoyao =createPerson('laoyao');
laoyao.sayName();
写到这里,你会发现其实跟我们平常写的代码很像:
var Person = function(name){
this.name=name;
}
Person.prototype = {
sayName:function(){
console.log(this.name);
}
};
var laoyaoq =new Person('laoyaoq');
laoyaoq.sayName();
我们来刻画一下new过程.我们假设new是一个函数,类似call和bind的那样的函数.
new Person('laoyaoq');我们换成Person.new('laoyao');
此函数定义如下:
Function.prototype.new = function (){
var that = Object.create(this.prototype);
this.apply(that,arguments);
return that;
}; var Person = function (name) {
this.name = name;
} Person.prototype ={
sayName:function(){
console.log(this.name);
}
};
var laoli = Person.new('laoli');
laoli.sayName();
其中这new函数,不是完整模拟new的(考虑返回值是否是对象).详细请看《js语言精粹》47页。其中this指向的是当前函数(Person)
如果上面的代码看不习惯的话,我们也可以发明如下的api:
myNew(Person, 'laoli')
var myNew = function() {
var Constructor = [].shift.call(arguments);
var that = Object.create(Constructor.prototype);
Constructor.apply(that, arguments);
return that;
}
var Person = function(name) {
this.name = name;
}
Person.prototype = {
sayName: function() {
console.log(this.name);
}
};
var laoyaoyao = myNew(Person, 'laoyaoyao');
laoyaoyao.sayName();
说明:上述代码改编于《JS设计模式与开发实践》第20页.
如果读者没有其他什么面向对象语言基础,
那么看此文,会觉得new是一个封装委托关系的过程.
而不是什么模拟java,模拟不彻底啥的.
所以在我看来,那些号召不要使用new的文章,也未必正确.
最后说下:这个委托的观点,《你不知道的javascript》有更详细的介绍.
prototype的本质的更多相关文章
- 简单理解js的prototype属性
在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的pr ...
- 对原型链的理解?prototype上都有哪些属性?
在js里,继承机制是原型继承.继承的起点是 对象的原型(Object prototype). 一切皆为对象,只要是对象,就会有 proto 属性,该属性存储了指向其构造的指针. Object prot ...
- JavaScript面向对象
理解对象 对象这个词如雷贯耳,同样出名的一句话:XXX语言中一切皆为对象! 对象究竟是什么?什么叫面向对象编程? 对象(object),台湾译作物件,是面向对象(Object Oriented)中的术 ...
- 【转】javascript面向对象编程
摘要:本文本来是想自己写的,奈何花了好长时间写好之后忘记保存,还按了刷新键,一键回到解放前,索性不写了,所以本文是转载的. 面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式,主要包括模块化. ...
- 【转】JavaScript面向对象
http://www.cnblogs.com/dolphinX/p/4385862.html 理解对象 对象这个词如雷贯耳,同样出名的一句话:XXX语言中一切皆为对象! 对象究竟是什么?什么叫面向对象 ...
- js面向对象(构造函数与继承)
深入解读JavaScript面向对象编程实践 Mar 9, 2016 面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式,主要包括模块化.多态.和封装几种技术. 对JavaScript而言,其 ...
- 《JS高程》实现继承的6种方式(完整版)
许多OO语言都支持 两种继承方式: (1)接口继承:只继承方法签名: (2)实现继承:继承实际的方法. ECMAScript 由于函数没有签名,无法实现接口继承,因此只支持实现继承,而且主要是依靠原型 ...
- 深入解读JavaScript面向对象编程实践
面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式,主要包括模块化.多态.和封装几种技术.对JavaScript而言,其核心是支持面向对象的,同时它也提供了强大灵活的基于原型的面向对象编程能力 ...
- js面向对象oop编程
理解对象 对象这个词如雷贯耳,同样出名的一句话:XXX语言中一切皆为对象! 对象究竟是什么?什么叫面向对象编程? 对象(object),台湾译作物件,是面向对象(Object Oriented)中的术 ...
随机推荐
- 成都Uber优步司机奖励政策(1月12日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Omad群组部署、依赖部署一键解决
本文来自网易云社区 作者:李培斌 前言 基于omad部署平台实现一键部署的实践已有很多成功的经验,杭研QA的技术先锋们也在ks圈里有很多不同的文章去阐述关于这类需求的实现和思路,当然包括我们金融事业部 ...
- ThinkPHP开启设置子域名笔记
一.ThinkPHP框架里 common下的config文件 'APP_SUB_DOMAIN_DEPLOY' => 1, // 开启子域名配置 'APP_SUB_DOMAIN_RULES' =& ...
- Siki_Unity_2-10_数据结构与算法
Unity 2-10 数据结构与算法 任务1-1:数据结构简介 数据结构:数据存储的结构,数据之间的关系 数据结构分类: 集合:同属于一个集合 线性结构:数据元素存在一对一的关系 树形结构:数据元素存 ...
- Siki_Unity_1-3_Unity零基础入门_古迹探险
1-3 Unity零基础入门 古迹探险 任务1/2:资料下载 链接:https://pan.baidu.com/s/1jHVymNk 密码:rbob 任务3:工程的创建和打开 Project:古迹探险 ...
- Python 的非正式介绍
在下面的例子中,通过提示符 (>>> 与 ...) 的出现与否来区分输入和输出:如果你想复现这些例子,当提示符出现后,你必须在提示符后键入例子中的每一个词:不以提示符开头的那些行是解 ...
- [JSON].value( keyPath )
语法:[JSON].value( keyPath ) 返回:[String | Null] 说明:获取指定键名路径值的字符串格式 示例: Set jsonObj = toJson("{bod ...
- Angular6项目搭建
参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/b076702elvw.html 安装工具: Nodejs, npm 最新版, h ...
- hadoop3.0新特性及新功能
Hadoop-3.0.0-alpha2版本发布,相比之前的hadoop-2.x有一系列的功能增强.但目前还是个alpha版本,有很多bug,且不能保证API的稳定和质量. 主要变化 Java最低版本要 ...
- CryptoZombies学习笔记——Lesson5
chapter1:token代币 简而言之,通证就是支持交易的包含一系列规范的函数接口的一个智能合约,发币可以用ERC20标准,但是像僵尸这种非同质化代币,需要用ERC721标准 chapter2:e ...