首先呢,prototype是对象里的一个内置属性,并且呢,这个属性是对于其他对象的一个引用。所以呢,思考下面的例子:

var obj = {a: 2
}
var myObj = Object.create(obj);
console.log(myObj.a); // 2
console.log(myObj === obj);  // false
console.log(Object.getPrototypeOf(myObj) === obj);  // true
Object.getPrototypeOf(myObj).a = 4
console.log(obj.a);  // 4

这里可以看到,实际上Object.create()是新建了一个对象,并且这个对象的prototype是obj的一个引用,所以呢,如果咱们直接修改prototype里面的值,原对象也就跟着变了。

很简单吧,那么如果执行如下代码的话,会发生什么呢?

myObj.a = 10;

是不是认为,还跟上面那个一样的,obj.a也变成10了呢?实际上不是的,他的运行机制要比咱们想的稍微复杂一点点。

实际上要分三种情况来看:

如果在prototype链上存在这个属性,并且没有标记为只读,那么就会在本对象上新建一个新的同名属性。

如果在prototype链上存在这个属性,并且标记为只读,那么将无法修改已有属性或在本对象上新建一个同名属性,如果是严格模式的话,还会报错。

如果在prototype链上只是存在此setter,那么一定会调用此setter,并不会添加属性到对象上,更不会重新定义这个setter

很枯燥是吧,来看例子,对照着上面的情况,好好的理解一下:

var obj = {a: 2,set c(num) {console.log('exec it');}
}
var myObj = Object.create(obj);
myObj.a = 10;
console.log(obj.a);  // 2
console.log(myObj.a);  // 10
Object.defineProperty(obj, 'b', {value: 3,writable: false
})
myObj.b = 10;
console.log(myObj.b); // 3
myObj.c = 20;  // "exec it"
console.log(myObj.c);    // undefined

假如上面的已经理解了,那么可以思考下下面的运行结果:

var obj = {a: 2
}
var myObj = Object.create(obj);
console.log(++myObj.a);  // 3
console.log(obj.a);  // 2

这个在咱们实际的编码中时有发生,看代码是想把a改成3,但是由于上面第一种情况的影响,实际上是新建了一个同名属性3,并且赋值给了myObj。

上面我们谈论的都是普通对象的prototype的一些特性,接下来,咱们就要讲关于new关键字相关的一些知识点了,思考下面的例子

function Foo() {}
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // true
var b = new Foo();
Object.getPrototypeOf(b).saySomething = function () {console.log('say something');
}
a.saySomething();  // "say something"

很明显,在new的过程中呢,生成了一个新对象,并且把Foo.prototype引用到了新对象的prototype。那么因为是引用,所以通过b改变其原型上的prototype的值,Foo.prototype里也会跟着改变。

那么new的过程,是不是一定引用的是函数的prototype呢?也不一定,比如说下面的例子。

function Foo() {return {a: 3}
}
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // false
console.log(Object.getPrototypeOf(a) === Object.prototype); // true
console.log(a.a); // 3

在这个例子中,由于new的时候,返回的是一个对象,所以最后实际上a最终引用的是Foo最后返回的那个小对象,所以其prototype就是Object.prototype,而不是Foo.prototype

甚至说,Foo.prototype也是可以被改变的,不过在这时候,new出来的对象,其prototype就是被改过的那个对象。

var protoObj = {b: 10
}
function Foo() {}
Foo.prototype = protoObj;
var a = new Foo();
console.log(Object.getPrototypeOf(a) === Foo.prototype);  // true
console.log(Object.getPrototypeOf(a) === protoObj); // true
console.log(a.b); // 10

你看,如果prototypeObj修改了默认的Foo.prototype,所以最后,实际上形成了这么一个引用链:a.prototype => foo.prototype => protoObj=>Object.prototype。

所以说结论吧,在new的时候,实际上执行会包含这么几步,

如果有return并且返回的是一个对象的话,则直接返回return后的那个对象。

反之,则新建一个对象。

并且吧函数的prototype引用到新建对象的prototype中。

所以说,原型,可以理解为我本来对象有一个prototype,引用着其他的对象,当我这个对象的prototype引用了另一个对象的prototype,一般情况会到Object.prototype为止,这样就组成了一个原型链,原型链也就是互相引用的引用链。而这个引用链是可以根据自己的需求去改。

好了,简短的一小节就完事了,如果有不明白的,或者有疏漏的地方,或者有什么地方想和我讨论的,可以留言给我哦。

本文转载自http://www.lht.ren/article/8/

Javascript基础之-原型(prototype)相关推荐

  1. JavaScript中的原型(prototype)与继承

    在JavaScript中,原型是用来模仿其他「类」语言继承机制的基础.原型并不复杂,原型只是一个对象. 一.原型对象 1.1 什么是原型对象 每当我们创建了一个函数后,这个函数就拥有了一个protot ...

  2. 前端面试知识点总结JavaScript基础之原型和原型链(二)

    一.JavaScript基础 原型和原型链 1.理解原型设计模式以及JavaScript中的原型规则 设计模式 1.工厂模式:在函数内建立一个对象,给对象赋予属性及方法再将对象返回设计模式. func ...

  3. 浅谈JavaScript中的原型prototype

    之前看过一些关于原型的知识,但总是看了以后没有及时应用,导致再看到一些代码是遇到还是搞不清楚,借此机会谈一下我对prototype的理解. 1.再谈原型之前,我们要知道什么是构造器函数,型如下例: f ...

  4. 【一天时间|JavaScript基础】原型和原型链

    一天时间系列文章是博主精心整理的面试热点问题和难点问题,吸收了大量的技术博客与面试文章,总结多年的面试经历,带你快速并高效地审视前端面试知识.直击技术痛点,主动出击,精密打击,这才是面试拿到高薪的秘诀 ...

  5. JavaScript中的原型prototype及原型链

    原型prototype 简介: prototype里面放置了一种类的公用的方法(构造函数:constructor)和类的信息.因此可以用来作为一种类的共享数据实现机制.这种共享的另一个好处的是减少了内 ...

  6. (转)【javascript基础】原型与原型链

    原文地址:http://www.cnblogs.com/allenxing/p/3527654.html 前言 原型是什么 理解原型对象 原型对象 isPrototypeOf hasOwnProper ...

  7. 说一说JavaScript 中的原型ProtoType

    一时兴起,写一遍博客吧. "函数是函数,函数也是对象" 相信学过js 的同学看到这句话很熟悉.我表示耳朵都听出茧子了. 我们都知道,在JavaScript中是没有类的概念的,那么怎 ...

  8. 浅谈JavaScript对象的原型prototype

    前提: 在JavaScript中一切皆对象,分为普通对象和函数对象,每个对象都有原型(undefined和null没有原型,所以undefined和null也就没有toSting方法). Object ...

  9. 夯实JavaScript基础之prototype, __proto__, instanceof

    function New(f){return function(){var o = {'__proto__': f.prototype};f.apply(o, arguments);return o; ...

最新文章

  1. Oracle12c多租户如何启动关闭CDB或PDB (PDB自动启动)
  2. matlab 图片转换
  3. EBB-11、Linux启动流程
  4. 我的爱好html子页模板,我的爱好
  5. apollo修改配置刷新bean_技术文档丨Apollo软件概述
  6. Hive的列分隔符和行分隔符
  7. json java的set函数,JsonConfig的jsonConfig.setExcludes的用法
  8. 【大数据】通过女票的淘宝历程,大白话讲解大数据各个方向的分工
  9. HTML网站去色代码
  10. 需求与商业模式分析-2-商业模式类型
  11. matlab函数sinh,matlab sinh 使用方法
  12. html pc页面连接到微信,PC上对限制在微信客户端访问的html页面进行调试
  13. 南朝皇帝简介-20170604
  14. 安卓(Android)手机如何安装APK?
  15. android手机传文件,Android手机间如何高速互传文件?
  16. 【论文阅读】MPViT : Multi-Path Vision Transformer for Dense Prediction
  17. 计算机类图书的中国法类号,公共书目查询
  18. 每日新闻:阿里云掀起新一轮价格大战;比特大陆正式发布AI芯片;百度区块链实验室落户海南;救市意图明显 北京海淀区成立百亿纾困基金...
  19. 2021年12月10日
  20. windows安装pscp工具,通过命令行上传到linux服务器

热门文章

  1. Python filter 函数 - Python零基础入门教程
  2. 通过docker无法访问到tomcat报页面404
  3. php时间转分钟前,PHP把时间转换成几分钟前几小时前几天前
  4. 娄底八中的初中计算机考试,众人同心勤耕耘 敢叫日月换新天
  5. xrdpdf卡片在哪可下载_暑假学习英语字母,就是这样简单(附可打印字母卡下载)...
  6. MySQL read-c_技术分享 | MySQL C API 参数 MYSQL_OPT_READ_TIMEOUT 的一些行为分析
  7. 计算机软件应用员,济宁计算机办公应用软件操作员
  8. php 内容编码错误,PHP输出缓冲,ob_gzhandler引起的内容编码错误?
  9. koa mysql mongodb_koa 操作MongoDB数据库
  10. android动画放大后缩小,Android 补间动画 scale(缩放)