原型对象 `prototype`
-  原型对象的所有属性和方法,都能被实例对象共享;
 
JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。

function Cat (name, color) {
this.name = name;
this.color = color;
} var cat1 = new Cat('小明', '白色'); cat1.name // '小明'
cat1.color // '白色'

构造函数缺点:

- 一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。
解决方法,就是 JavaScript 的原型对象`prototype`,因为原型对象的所有属性和方法,都能被实例对象共享。
function Cat (name, color) {
this.name = name;
}
Cat.prototype.color ="白色";
}
var cat1 = new Cat('巧克力');
var cat2 = new Cat('布丁');
cat1.color //白色
cat2.color//白色
JavaScript规定,每个函数都有一个`prototype`属性,指向一个对象。
- 对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。
- 实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法。
function f() {}
typeof f.prototype // "object"
每个 JS 对象都有 `__proto__` 属性,这个属性可以访问到 原型(`[[prototype]]`) 内部属性。这个属性在现在来说已经不推荐直接去使用它了。

原型链

 - 任何对象,都可以充当其他对象的原型;原型对象也有自己的原型。
 - 对象到原型,再到原型的原型,一层层向上找到`Object.prototype` 形成原型链。
可以说 基本上所有对象都继承了`Object.prototype`的属性;而 `Object.prototype` 的原型是 `null`
通过 `getPrototypeOf` 方法返回参数对象原型
Object.getPrototypeOf(Object.prototype) //null
 读取对象属性时,引擎会先在自身属性上查找,没有就查找原型,一级级向上查找,如果到`Object.prototype`还是没有,则返回`undefined`。
**一级级向上,对性能有影响,寻找的层级越多,性能影响越大**
 
**原型链:**

 
- 实例 F1 通过`__proto__` 访问对应构造函数的原型 -> `FOO.prototype`
 
- 函数原型再通过`__proto__` 访问Object的原型 -> `Object.prototype`
 
- Object的原型的`__proto__` 指向 `null`
 
- 构造函数 `Foo.prototype` 通过`constructor`访问构造函数本身
 
- `Object.constructo` 指向 `Function`
 
- `Function.constructo` 指向 本身
 
- `Function.__proto__` 指向一个匿名函数
 
- 每个构造函数通过 `prototype` 访问原型
**只有函数才拥有`prototype`属性,基本上所有函数都有这个属性**
let fun = Function.prototype.bind()
当声明一个函数时自动创建 `prototype` 属性,
这个属性的值是一个对象(也就是原型),且只有一个属性 `constructor`
 

`constructor`

`prototype` 有一个属性 `constructor`,默认指向原型所在的构造函数
function Fn (){}
var f = new Fn ();
f.constructor == Fn //true
f.constructor == Function //false //可以从实例对象新建另一个实例
var b =new f.constructor();
b.constructor == Fn //true
`constructor `是一个公有且不可枚举的属性。一旦我们改变了函数的 prototype ,那么新对象就没有这个属性了,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。
function A(){}
console.log(A.prototype) // {constructor: ƒ}constructor: ƒ A()__proto__: Object
A.prototype="a"
console.log(A.prototype) //"a"

constructor作用:

- 让实例对象知道是什么函数构造了它,可以得知某个实例对象,是哪一个构造函数产生的。
- 如果想给某些类库中的构造函数增加一些自定义的方法,就可以通过 xx.constructor.method 来扩展

\_\_proto\_\_

基本上每个对象都有的隐式原型属性,指向创建该对象的构造函数的原型,实际指向`[[prototype]]`, 内部属性,我们并不能访问到,所以使用 _proto_ 来访问。
console.log({})
//__proto__: Objectconstructor: ƒ Object()hasOwnProperty: ....

当我们使用 new 操作符时,生成的实例对象拥有了 `__proto__`属性。

function Foo() {}
// 这个函数是 Function 的实例对象
// function 就是一个语法糖
// 内部调用了 new Function(...)
const a =1;
const fn = new Function("console.log(a)") // Function 的this始终指向 全局对象,除非手动改变this指向
fn()//
- 所有对象都可以通过原型链最终找到 Object.prototype ,虽然 Object.prototype 也是一个对象,但是这个对象却不是 Object 创造的,而是引擎自己创建了 `Object.prototype` 。
可以这样说,所有实例都是对象,但是对象不一定都是实例。
-首先引擎创建了 Object.prototype ,然后创建了 Function.prototype ,并且通过__proto__ 将两者联系了起来。
- Function.prototype 以后才有了 function Function() ,然后其他的构造函数都是 function Function() 生成的。
- 函数通过 `new Function()` 生成, 不是所有函数都是 `new Function() `产生的。 
 
总结:
> 1. Object 是所有对象的爸爸,所有对象都可以通过__proto__ 找到它
 
> 2. Function 是所有函数的爸爸,所有函数都可以通过__proto__ 找到它
 
> 3. Function.prototype 和 Object.prototype 是两个特殊的对象,他们由引擎来创建
 
> 4. 除了以上两个特殊对象,其他对象都是通过构造器 new 出来的
 
> 5. 函数的 prototype 是一个对象,也就是原型
 
对象的__proto__ 指向原型,__proto__将对象和原型连接起来组成了原型链

JavaScript 对象继承 OOP (三)

JavaScript 原型链 OOP(二)的更多相关文章

  1. JavaScript学习总结(十七)——Javascript原型链的原理

    一.JavaScript原型链 ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法.其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法.在JavaScript中, ...

  2. JavaScript原型链及其污染

    JavaScript原型链及其污染 一.什么是原型链? 1.JavaScript中,我们如果要define一个类,需要以define"构造函数"的方式来define: functi ...

  3. javascript原型链中 this 的指向

    为了弄清楚Javascript原型链中的this指向问题,我写了个代码来测试: var d = { d: 40 }; var a = { x: 10, calculate: function (z) ...

  4. 明白JavaScript原型链和JavaScrip继承

    原型链是JavaScript的基础性内容之一.其本质是JavaScript内部的设计逻辑. 首先看一组代码: <script type="text/javascript"&g ...

  5. Javascript 原型链资料收集

    Javascript 原型链资料收集 先收集,后理解. 理解JavaScript的原型链和继承 https://blog.oyanglul.us/javascript/understand-proto ...

  6. 资料--JavaScript原型链

    JavaScript原型链 原文出处:https://www.cnblogs.com/chengzp/p/prototype.html 目录 创建对象有几种方法 原型.构造函数.实例.原型链 inst ...

  7. JavaScript原型链:prototype与__proto__

    title: 'JavaScript原型链:prototype与__proto__' toc: false date: 2018-09-04 11:16:54 主要看了这一篇,讲解的很清晰,最主要的一 ...

  8. JS面向对象组件(二)--Javascript原型链

    原型链 : 实例对象与原型之间的连接,叫做原型链 –__proto__( 隐式连接 ),这就是原型链,平时我们是看不到的. 原型链的最外层 : Object.prototype function Aa ...

  9. 图解Javascript原型链

    本文尝试阐述Js中原型(prototype).原型链(prototype chain)等概念及其作用机制.上一篇文章(图解Javascript上下文与作用域)介绍了Js中变量作用域的相关概念,实际上关 ...

随机推荐

  1. mybatis 批量update两种方法对比

    <!-- 这次用resultmap接收输出结果 --> <select id="findByName" parameterType="string&qu ...

  2. Django 自定义模板标签 报错django.template.exceptions.TemplateSyntaxError: '####' is not a registered tag library. Must be one of:

    我写代码遇到这个错误,但是发现程序没有写错,好像是程序有缓存,重新运行几次就好了. 自定义模板标签,可以不用写views,url直接通过自定义函数把变量传给模板. 具体实现: 1.在app下新建Pyt ...

  3. 平衡树学习笔记(2)-------Treap

    Treap 上一篇:平衡树学习笔记(1)-------简介 Treap是一个玄学的平衡树 为什么说它玄学呢? 还记得上一节说过每个平衡树都有自己的平衡方式吗? 没错,它平衡的方式是......rand ...

  4. cmake相关问题

    一.cmake升级 在ubuntu 16.04下面把cmake 由 3.5.1升级到 3.11,具体的流程如下所述. (1) sudo apt-get install build-essential ...

  5. springboot整合mybatis,redis,代码(三)

    一 说明 接着上篇讲述redis缓存配置的用法: 二 正文 首先要使用缓存就必须要开开启缓存,第二步是需要开redis-server 下载redis包之后,点击图中两个都可以开启redis 怎么看是否 ...

  6. C语言变量:名称、地址和值

    变量的名称.地址和变量的值之间关系密切. 我们可以认为变量有两个属性:名称和值(其他属性暂不讨论): 计算机编译和加载后也认为变量有两个属性:地址和值.地址就是变量在计算机内部的名称. 许多语言中地址 ...

  7. [USACO19FEB]Moorio Kart(DP)

    Luogu5243 题解 即O(N^2)暴力统计出每个森林的路径,从ctgn个集合中各选出一个数,使得长度>=Y的方案数. 用背包统计.具体实现: \(dp[i+j][0]\leftarrow ...

  8. day15 面向对象 成员

    成员 1. 变量 1.实例变量 格式: 变量.xxx=xx (称为实例变量,也叫属性,字段)给对象用的 2.类变量 类变量:直接写在类中的变量就是类变量,类变量一般用类名来访问 其实就是类中相同的属性 ...

  9. 用vector实现二维向量

    如果一个向量的每一个元素是一个向量,则称为二维向量,例如 vector<vector<int> >vv(3, vector<int>(4));//这里,两个“> ...

  10. CSS十问——好奇心+刨根问底=CSSer(转)

    最近有时间,想把酝酿的几篇博客都写出来,今天前端小学生带着10个问题,跟大家分享一下学习CSS的一些体会,我觉得想学好CSS,必须保持一颗好奇心和刨根问底的劲头,而不是复制粘贴,得过且过.本人能力有限 ...