1、说明

函数(Function)才有prototype属性,对象(除Object)拥有__proto__。

2、prototype与__proto__区别

示例:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>prototype与__proto__区别</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
var a = {};
console.log(a.prototype); //undefined
console.log(a.__proto__); //Object {} var b = function() {}
console.log(b.prototype); //b {}
console.log(b.__proto__); //function() {}
</script>
</body> </html>

控制台输出:

(3)__proto__指向

示例:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>__proto__指向</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
/*1、字面量方式*/
var a = {};
console.log(a.__proto__); //Object {} console.log(a.__proto__ === a.constructor.prototype); //true /*2、构造器方式*/
var A = function() {};
var b = new A();
console.log(b.__proto__); //A {} console.log(b.__proto__ === b.constructor.prototype); //true /*3、Object.create()方式*/
var a1 = {
a: 1
}
var a2 = Object.create(a1);
console.log(a2.__proto__); //Object {a: 1} console.log(a2.__proto__ === a2.constructor.prototype); //false(此处即为图1中的例外情况)
</script>
</body> </html>

控制台输出:

(4)原型链

(1)是__proto__指向的一条指针链!

(2)查找属性时,首先先查找自身属性,找不到的话,在查找原型链上的属性。但是不会查找自身的prototype属性。

示例代码:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>属性查找</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
Function.prototype.age = 20;
let b = function() {}
b.prototype.age = 10;
console.log(b.age)//输出20
</script>
</body> </html>

示例:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>原型链</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
var A = function() {};
var a = new A();
console.log(a.__proto__); //A {}(即构造器function A 的原型对象)
console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象)
console.log(a.__proto__.__proto__.__proto__); //null
</script>
</body> </html>

(5)prototype

prototypelength是每一个函数类型自带的两个属性,而其它非函数类型并没有,这一点之所以比较容易被忽略或误解,是因为所有类型的构造函数本身也是函数,所以它们自带了prototype属性:

示例:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>prototype</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
console.log(Object.prototype); //=> {} console.log(Function.prototype); //=> [Function: Empty] console.log(String.prototype); //=> [String: '']
</script>
</body> </html>

除了prototype之外,Js中的所有对象(undefinednull等特殊情况除外)都有一个内置的[[Prototype]]属性,指向它“父类”的prototype,这个内置属性在ECMA标准中并没有给出明确的获取方式,但是许多Js的实现(如Node、大部分浏览器等)都提供了一个__proto__属性来指代这一[[Prototype]],我们通过下面的例子来说明实例中的__proto__是如何指向构造函数的prototype的:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>prototype与__proto__</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
var Person = function() {}; Person.prototype.type = 'Person'; Person.prototype.maxAge = 100; var p = new Person(); p.name = 'rainy'; Person.prototype.constructor === Person; //=> true p.__proto__ === Person.prototype; //=> true console.log(p.prototype); //=> undefined
console.log(p.maxAge); //100
console.log(p.__proto__.maxAge); //100
console.log(p.name); //rainy
console.log(p.__proto__.name); //undefined
</script>
</body> </html>

图示:

Person是一个函数类型的变量,因此自带了prototype属性,prototype指向中的Person.prototype对象。Person.prototype.constructor又指向Person本身;通过new关键字生成的Person类的实例p1,通过__proto__属性指向了Person的原型。这里的__proto__只是为了说明实例p1在内部实现的时候与父类之间存在的关联(指向父类的原型),在实际操作过程中实例可以直接通过.获取父类原型中的属性,从而实现了继承的功能。

(6)原型链

示例代码:

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>prototype与__proto__</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
var Obj = function() {}; var o = new Obj(); o.__proto__ === Obj.prototype; //=> true o.__proto__.constructor === Obj; //=> true Obj.__proto__ === Function.prototype; //=> true Obj.__proto__.constructor === Function; //=> true Function.__proto__ === Function.prototype; //=> true Object.__proto__ === Object.prototype; //=> false Object.__proto__ === Function.prototype; //=> true Function.__proto__.constructor === Function; //=> true Function.__proto__.__proto__; //=> {} Function.__proto__.__proto__ === o.__proto__.__proto__; //=> true o.__proto__.__proto__.__proto__ === null; //=> true
</script>
</body> </html>

(7)null与undefined

null与undefined 无原型

//报错
console.log(Object.getPrototypeOf(undefined))
//报错
console.log(Object.getPrototypeOf(null))

从上面的例子和图解可以看出,prototype对象也有__proto__属性,向上追溯一直到null

(8)原型链的遍历过程(一直到null)

<!DOCTYPE html>
<html lang="zh"> <head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>原型链的遍历过程</title>
</head> <body>
<script src="https://cdn.bootcss.com/lodash.js/4.17.10/lodash.min.js"></script>
<script type="text/javascript">
let a = 1
console.log(a.__proto__ === Number.prototype) //true
console.log(Number.__proto__ === Function.prototype) //true
console.log(Function.__proto__ === Function.prototype) //true
console.log(Function.__proto__.__proto__ === Object.prototype) //true
console.log(Function.__proto__.__proto__.__proto__)
</script>
</body> </html>

(9)获取原型对象

Object.getPrototypeOf(object)

(10)原型上可遍历的属性

__proto__ 隐式原型 prototype显示原型

js 原型链 prototype __proto__的更多相关文章

  1. js原型链prototype与__proto__以及new表达式

    对象模型的细节 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Details_of_the_Object_Model

  2. JavaScript原型链:prototype与__proto__

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

  3. JS原型链

    JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...

  4. 深入分析JS原型链以及为什么不能在原型链上使用对象

    在刚刚接触JS原型链的时候都会接触到一个熟悉的名词:prototype:如果你曾经深入过prototype,你会接触到另一个名词:__proto__(注意:两边各有两条下划线,不是一条).以下将会围绕 ...

  5. JS 原型链图形详解

    JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语 ...

  6. js 原型链和继承(转)

    在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var ob ...

  7. 一张图看懂 JS 原型链

    JS 原型链,画了张图,终于理清楚各种关系有木有 写在最后: __proto__是每个对象都有的一个属性,而prototype是函数才会有的属性!!! function Person() { } 是函 ...

  8. 简单粗暴地理解js原型链–js面向对象编程

    简单粗暴地理解js原型链–js面向对象编程 作者:茄果 链接:http://www.cnblogs.com/qieguo/archive/2016/05/03/5451626.html 原型链理解起来 ...

  9. JS原型链与继承别再被问倒了

    原文:详解JS原型链与继承 摘自JavaScript高级程序设计: 继承是OO语言中的一个最为人津津乐道的概念.许多OO语言都支持两种继承方式: 接口继承 和 实现继承 .接口继承只继承方法签名,而实 ...

随机推荐

  1. JAVA变成把一个整数分解成多个质数的积

    /* * TestTengXun.java * Version 1.0.0 * Created on 2017年12月2日 * Copyright ReYo.Cn */ package reyo.sd ...

  2. SharePoint JavaScript API 根据文件路径删除文件

    最近,有这么个需求,然后写了几行代码,记录一下.有需要的可以参考一下. 有几个需要注意的地方,就是文件URL要传相对地址,使用网站对象之前要Load一下. 当然,如果你的网站不在根路径下,还可以用oW ...

  3. JAVA设计模式-设计原则

    6大原则: 单一职责原则 里氏替换原则 依赖倒置原则 接口隔离原则 迪米特法则 开闭原则 一.单一职责原则 定义:应该有且仅有一个原因引起类的变更 带来的好处: 类的复杂性降低,实现什么职责有清晰明确 ...

  4. jscript调用bat注意事项

    开发的游戏项目,需要一个工具,对指定的资源进行复制.加密,然后打包.之前打包时都手工操作,复制与加密这二步分别写了几个工具(lua加密与图片资源加密是分开的),后来感觉bat操作路径特别麻烦,所以我改 ...

  5. 实用ExtJS教程100例-006:ExtJS中Window的用法示例

    在前面几个示例中,我们演示了MessageBox的各种用法,今天这篇文章将演示如何使用Window. 我们首先来创建一个窗口: var win = Ext.create("Ext.windo ...

  6. centos7更改为启动桌面或命令行模式

    进入cenos7的命令行模式 终端输入“init 3”回车进入命令行模式 登录成功后 # systemctl get-default //获取当前系统启动模式 查看配置文件 # cat /etc/in ...

  7. Gerrit代码审查工具

    1 Gerrit简介 Gerrit,一种免费.开放源代码的代码审查软件,使用网页界面.利用网页浏览器,同一个团队的软件程序员,可以相互审阅彼此修改后的程序代码,决定是否能够提交,退回或者继续修改. 1 ...

  8. [转]RSA,DSA等加解密算法介绍

    From : http://blog.sina.com.cn/s/blog_a9303fd90101cgw4.html 1)      MD5/SHA MessageDigest是一个数据的数字指纹. ...

  9. 生成学习算法(Generative Learning algorithms)

    一.引言 前面我们谈论到的算法都是在给定\(x\)的情况下直接对\(p(y|x;\theta)\)进行建模.例如,逻辑回归利用\(h_\theta(x)=g(\theta^T x)\)对\(p(y|x ...

  10. AS 阿里巴巴Java开发规约 CheckStyle-IDEA

    Alibaba Java Coding Guidelines 简介 github地址:https://github.com/alibaba/p3c  官方文档    阿里巴巴Java开发手册(纪念版) ...