一文彻底搞懂JavaScript中的prototype
prototype初步认识
在学习JavaScript中,遇到了prototype,经过一番了解,知道它是可以进行动态扩展的
function Func(){};
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
即最开始创建的函数Func并没有var1变量,但是我们可以进行扩展,并且让根据其创建的对象也有var1变量
函数有prototype属性,函数创建的对象没有
这个时候,尝试对var1变量进行扩展,但是居然报错了
function Func(){};
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
获得当前对象的属性
那我们现在有一个疑问:func1应该是有var1变量的,那上面报错意思是func1没有prototype属性/方法咯?我如何查看一个对象到底有没有这个属性呢?
我们知道,可以用in来查看对象是否有属性
function Func(){};
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
现在我们知道了,func1确实没有prototype属性/方法,那func1也就是函数创建的对象都不能扩展了吗?回答这个问题之前,我们还要明白一个问题,func1中的var1变量是自己的吗?怎么区分呢?
function Func(){};
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
console.log("-----接下来看hasOwnProperty函数-----")
func1.var2 = "func1自己的变量"
console.log(func1.hasOwnProperty("var2")) //true
console.log(func1.hasOwnProperty("var1")) //false
我们可以用hasOwnProperty函数来知道变量是不是扩展的了
父和子的扩展
这里我把Func当成父,把func1当成子来作为个人理解

function Func() { };
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
console.log("-----接下来看hasOwnProperty函数-----")
func1.var2 = "func1自己的变量"
console.log(func1.hasOwnProperty("var2")) //true
console.log(func1.hasOwnProperty("var1")) //false
console.log("-----接下来看proto-----")
console.log(Func.hasOwnProperty("__proto__")) //false
console.log(func1.hasOwnProperty("__proto__")) //false
console.log(func1.__proto__ === Func.prototype) // true
console.log(func1.__proto__ == Func.prototype) // true
console.log(func1.prototype == Func.prototype) // false
console.log(func1.__proto__.var1) //Func进行了扩展
console.log(func1.var1) //Func进行了扩展
这里可以看到func1本身没有__proto__属性,但是和Func的protype属性是一样的
子的proto和prototype的区别
到这里你肯定想问,对于子func1的__proto__和prototype有什么区别呢?
首先子func1并没有prototype属性
其实双下划线表示隐藏的,不太想让外界访问到,这么思考,父Func不仅创建了子func1,而且创建了子func2,这时候如果子func1通过__proto__修改了var1,那么父Func的var1跟着变化,并且func2的var1也会变化,但是如果func1直接修改var1,那么父Func和子func2的var1都不会变化
function Func() { };
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
console.log("-----接下来看hasOwnProperty函数-----")
func1.var2 = "func1自己的变量"
console.log(func1.hasOwnProperty("var2")) //true
console.log(func1.hasOwnProperty("var1")) //false
console.log("-----接下来看proto-----")
console.log(Func.hasOwnProperty("__proto__")) //false
console.log(func1.hasOwnProperty("__proto__")) //false
console.log(func1.__proto__ === Func.prototype) // true
console.log(func1.__proto__ == Func.prototype) // true
console.log(func1.prototype == Func.prototype) // false
console.log(func1.__proto__.var1) //Func进行了扩展
console.log(func1.var1) //Func进行了扩展
console.log("-----接下来看proto和prototype的区别-----")
func1.var1 = "func1进行了扩展"
console.log(func1.var1) //func1进行了扩展
console.log(Func.prototype.var1) //Func进行了扩展
扩展得到的东西到底从哪来的
那么子func1我们前面使用了hasOwnProperty属性,但是func1本身并没有这个属性,那么它从哪来的?
function Func() { };
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
console.log("-----接下来看hasOwnProperty函数-----")
func1.var2 = "func1自己的变量"
console.log(func1.hasOwnProperty("var2")) //true
console.log(func1.hasOwnProperty("var1")) //false
console.log("-----接下来看proto-----")
console.log(Func.hasOwnProperty("__proto__")) //false
console.log(func1.hasOwnProperty("__proto__")) //false
console.log(func1.__proto__ === Func.prototype) // true
console.log(func1.__proto__ == Func.prototype) // true
console.log(func1.prototype == Func.prototype) // false
console.log(func1.__proto__.var1) //Func进行了扩展
console.log(func1.var1) //Func进行了扩展
console.log("-----接下来看proto和prototype的区别-----")
func1.var1 = "func1进行了扩展"
console.log(func1.var1) //func1进行了扩展
console.log(Func.prototype.var1) //Func进行了扩展
console.log("-----接下来看hasOwnProperty从哪来的-----")
console.log(Func.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
console.log(Func.__proto__.hasOwnProperty("hasOwnProperty")) // false
console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
从父和子那节的那张图也可以看出,使用两次__proto__即可找到hasOwnProperty属性
那么到此也就了解了prototype和__proto__了
附上完整代码两段供测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Fun(){
}
var func1 = new Fun()
console.log(typeof Fun) // function
console.log(typeof func1) // object
console.log(func1.prototype) // undefined
console.log(typeof func1.__proto__) // object
console.log(func1.__proto__) // 一个比较复杂的object
console.log(func1.__proto__ == Fun.prototype) // true
console.log(func1.prototype == Fun.prototype) // false
Fun.prototype.var1 = "hello"
console.log(func1.var1) // hello
console.log(func1.__proto__.var1) // hello
func1.var1 = "yes"
console.log(Fun.var1) // undefined
console.log(func1.var1) // yes
console.log(Fun.prototype.var1) // hello
console.log(func1.__proto__.var1) // hello
console.log(func1.prototype) // undefined
func1.__proto__.var1 = "hhh"
console.log(func1.__proto__.var1) // hhh
console.log(Fun.prototype.var1) // hhh
console.log(Fun.__proto__.var1) // undefined
console.log("------测试原型对象里面的proto-------")
console.log(func1.hasOwnProperty("var1")) // true
console.log(func1.hasOwnProperty("__proto__"))
console.log(Fun.hasOwnProperty("hasOwnProperty")) // false
console.log(Fun.hasOwnProperty("__proto__")) // false
console.log(Fun.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
console.log(Fun.__proto__.hasOwnProperty("hasOwnProperty")) // false
console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
function Func() { };
var func1 = new Func;
console.log(func1.var1) //undefined
Func.prototype.var1 = "Func进行了扩展"
console.log(func1.var1) //Func进行了扩展
console.log(Func.var1)
// func1.prototype.var1 = "func1进行了扩展" //Uncaught TypeError: Cannot set properties of undefined (setting 'var1')
console.log("var1" in func1) //true
console.log("prototype" in func1) //false
console.log("-----接下来看hasOwnProperty函数-----")
func1.var2 = "func1自己的变量"
console.log(func1.hasOwnProperty("var2")) //true
console.log(func1.hasOwnProperty("var1")) //false
console.log("-----接下来看proto-----")
console.log(Func.hasOwnProperty("__proto__")) //false
console.log(func1.hasOwnProperty("__proto__")) //false
console.log(func1.__proto__ === Func.prototype) // true
console.log(func1.__proto__ == Func.prototype) // true
console.log(func1.prototype == Func.prototype) // false
console.log(func1.__proto__.var1) //Func进行了扩展
console.log(func1.var1) //Func进行了扩展
console.log("-----接下来看proto和prototype的区别-----")
func1.var1 = "func1进行了扩展"
console.log(func1.var1) //func1进行了扩展
console.log(Func.prototype.var1) //Func进行了扩展
console.log("-----接下来看hasOwnProperty从哪来的-----")
console.log(Func.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
console.log(Func.__proto__.hasOwnProperty("hasOwnProperty")) // false
console.log(func1.__proto__.__proto__.hasOwnProperty("hasOwnProperty")) // true
</script>
</body>
</html>
一文彻底搞懂JavaScript中的prototype的更多相关文章
- 来一轮带注释的demo,彻底搞懂javascript中的replace函数
javascript这门语言一直就像一位带着面纱的美女,总是看不清,摸不透,一直专注服务器端,也从来没有特别重视过,直到最近几年,javascript越来越重要,越来越通用.最近和前端走的比较近,借此 ...
- 帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...
- 彻底搞懂JavaScript中的继承
你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- "继承"就和"原型链"这一概念息息相关.甚至可以说,所谓的"原型链&q ...
- 一文彻底搞懂Java中的环境变量
一文搞懂Java环境变量 记得刚接触Java,第一件事就是配环境变量,作为一个初学者,只知道环境变量怎样配,在加上各种IDE使我们能方便的开发,而忽略了其本质的东西,只知其然不知其所以然,随着不断的深 ...
- 一张图搞懂 Javascript 中的原型链、prototype、__proto__的关系 转载加自己的总结
1. JavaScript内置对象 所谓的内置对象 指的是:JavaScript本身就自己有的对象 可以直接拿来就用.例如Array String 等等.JavaScript一共有12内置对象 ...
- 彻底搞懂javascript中的match, exec的区别
在工作中经常发现一些同学把这两个方法搞混,以致把自己弄的很郁闷.所以我和大家一起来探讨一下这两个方法的奥妙之处吧. 我们分以下几点来讲解: 相同点: 1.两个方法都是查找符合条件的匹配项,并以数组形式 ...
- 一分钟搞懂JavaScript中的JSON对象
JSON(JavaScript Object Notation)是表示值和对象的通用格式. JavaScript 提供了如下方法: JSON.stringify 将对象转换为 JSON. JSON.p ...
- 来吧,一文彻底搞懂Java中的Comparable和Comparator
大家好,我是沉默王二,今天在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题.比如说:Java 的 Comparable 和 Comparator 是兄弟俩吗?像这类灵魂拷问 ...
- 来吧,一文彻底搞懂Java中最特殊的存在——null
没事的时候,我并不喜欢逛 P 站,而喜欢逛 programcreek 这些技术型网站,于是那天晚上,在夜深人静的时候,我就发现了一个专注基础但不容忽视的主题.比如说:Java 中的 null 到底是什 ...
随机推荐
- Python form...import...和import的区别(自己理解的)
Python有两种导入包和模块的方式,区别如下 form...import... import 相对导包 导入不同包子模块 可以导入模块所需变量/函数/类 init文件的__all__特殊变量(模 ...
- 什么是 bean 的自动装配?
Spring 容器能够自动装配相互合作的 bean,这意味着容器不需要和配置,能通 过 Bean 工厂自动处理 bean 之间的协作.
- java-等待唤醒机制(线程中的通信)-线程池
为什么需要线程间的通信 多个线程并发执行时,在默认情况下CPU时随机切换线程的,当我们需要多个线程共同完成一件任务,并且 希望他们有规律的执行,那么多线程之间需要一些协调通信,以此来帮我们达到多线程共 ...
- 深入理解FIFO(包含有FIFO深度的解释)
FIFO: 一.先入先出队列(First Input First Output,FIFO)这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令. 1.什么是FIFO? FIFO是 ...
- 路径规划—BUG算法
- python学习笔记(三)——函数
函数定义 def 函数名(形参 . . . ) 函数体 1. 函数参数 返回值:可以有一个或多个 形参:支持默认形参.关键字形参.可变参数形参等 1.1 必须参数 调用时传入的参数必须与定义时相同. ...
- js常用的函数库
阻止冒泡.默认行为.事件捕获 /* funname preventEventPropagation * desc 阻止冒泡事件&阻止默认行为&阻止事件捕获 * params {name ...
- Graphics 与 DisplayObject 的关系
在原生 Canvas 中,其实并没有 DisplayObject 的概念,它只有绘制图像的概念. 大部分的原生绘制图形或图像的 API 一般是这样的: api(x, y, ...) 例如 rect 就 ...
- Java/C++实现解释器模式---机器人控制程序
某机器人控制程序包含一些简单的英文指令,其文法规则如下: expression ::= direction action distance | composite composite ::= expr ...
- win10 Celery异步任务报错: Task handler raised error: ValueError('not enough values to unpack (expected 3, got 0)
示例代码如下: from celery import Celery app = Celery('tasks', backend='redis://×××:6379/1', broker='redis: ...