摘要:构造函数创建一个对象上边这个例子,我们通过构造函数创建了一个实例,从这个实例到他的原型到最后得,他们之间得关系,就形成了一个原型链和首先上边这个例子里边,我们声明了一个构造函数,在后再这个构造函数里边有一个的属性。
构造函数创建一个对象
function Person() { } var person = new Person(); person.name = "zhangsan"; console.log(person.name) // zhangsan
上边这个例子,我们通过构造函数创建了一个实例,从这个实例到他的原型到最后得object,他们之间得关系,就形成了一个原型链
prototype __proto__ 和 constructor首先上边这个例子里边,我们声明了一个构造函数,在后再这个构造函数里边有一个prototype的属性。
注意这个prototype属性,是只有函数才会有属性
Person.prototype.name = "zhangsan"; var person1 = new Person(); var person2 = new Person(); console.log(person1.name) // zhangsan console.log(person2.name) // zhangsan
首先我们看到再函数的prototype属性上边我们定义了一个name属性,然后通过new创建了两个实例,
然后通过调用实例的name属性,也可以拿到构造函数prototype属性上边的name属性,
那么这个prototype到底是有什么用处呢,
prototype
这个只有函数才会有的属性,他其实指向了一个对象,而这个对象就是调用了构造函数创建实例的原型
,可以理解成是person1,person2在创建的时候从他们的原型把原型的属性委托给了person1和person2
这里为什么不叫他继承,因为继承的定义是赋值一个一模一样的实例出来,但是js里边并不会复制
proto
这个__proto__属性是每个对象实例都会有的一个属性,这个属性也会指向该对象的原型
function Person() {} var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true
可以粘贴一下代码到浏览器打印一下person1 可以看到__proto__这个属性
constructor
constructor这个属性之前我也叫他构造函数,叫习惯了,因为每个原型上边都会有一个constructor这个属性,指向其相关的构造函数
function Person() {} console.log(Person === Person.prototype.constructor); // true原型链的查找机制
首先在你创建一个实例的时候,你去读取实例上边的属性,他会首先再实例上边去查找,如果找不到,那么就去这个实例的原型上边去找,如果还是找不到,就会去原型的原型上边去找,直到最后找到Object对象,当然object对象也是有原型的 就是null
记得之前的时候,遇到过这么一个问题就是typeof null的 时候为什么是个object,记得当时得到的答案是说null是一个对象的空指针,从现在来看null打印object是有原因的
那么还是查找不到的话会怎么样的,不要慌(.゚ー゚), 他会返给你一个undefined(.゚ー゚)
最后拉一张图
图中蓝色的这个链状的结构的线就是原型链
js的作用域首先什么叫做作用域
作用域是指程序源代码中定义变量的区域。作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。
JavaScript 采用词法作用域(lexical scoping),也就是静态作用域。
var value = 1; function foo() { console.log(value); } function bar() { var value = 2; foo(); } bar();
网上拿来的例子,直接说过程
在执行阶段执行foo的时候,直接在foo寻找value ,因为js是静态作用域,所以在foo里边没有找到的时候,直接去上一层找,最后结果是1
var value = 1; function bar() { var value = 2; console.log(value); } bar();
同理这段代码bar里边有value 直接打印2
那么再看一个例子
var scope = "global scope"; function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f(); } checkscope();
这个例子会打印出什么,大家可以猜一猜
结果就是local scope
那么为什么上边的第一段代码里边同样是在函数里边执行另一个函数,但是他不会用第一个函数里边的变量呢,
原因就是js是静态作用域,js执行一个函数的时候分为两个阶段,首先会解析一变,这个时候确定了词法作用域和this指向,属性声明等,然后才是函数执行阶段
函数的作用域是基于函数创建的位置的,所以第一段代码和下边这段代码的函数作用域是不想同的
说到这里的时候,我在上文中提到了执行上下文和函数执行的过程,之前在我得另一篇博客里边写道过,有兴趣的可以去看下 js的堆栈队列
以上是我对js原型链和作用域的一些认识,有不足的希望指正,之前在博客园写的。搬过来的
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/105461.html
摘要:我们用一张图表示构造函数和实例原型之间的关系好了构造函数和实例原型之间的关系我们已经梳理清楚了,那我们怎么表示实例与实例原型,也就是或者和之间的关系呢。 开篇: 在Brendan Eich大神为JavaScript设计面向对象系统的时候,借鉴了Self 和Smalltalk这两门基于原型的语言,之所以选择基于原型的面向对象系统,并不是因为时间匆忙,它设计起来相对简单,而是因为从一开始B...
摘要:我们用一张图表示构造函数和实例原型之间的关系好了构造函数和实例原型之间的关系我们已经梳理清楚了,那我们怎么表示实例与实例原型,也就是或者和之间的关系呢。 开篇: 在Brendan Eich大神为JavaScript设计面向对象系统的时候,借鉴了Self 和Smalltalk这两门基于原型的语言,之所以选择基于原型的面向对象系统,并不是因为时间匆忙,它设计起来相对简单,而是因为从一开始B...
摘要:原型链与继承当谈到继承时,只有一种结构对象。如果对该图不怎么理解,不要着急,继续往下看基于原型链的继承对象是动态的属性包指其自己的属性。当使用操作符来作用这个函数时,它就可以被称为构造方法构造函数。 原型链与继承 当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object )都有一个私有属性(称之为proto)指向它的原型对象(prototype)。该原型对象也...
摘要:原文发自我的博客易企秀招聘啦首先我们先来回顾以下中出现的原型继承原型继承自如果我们要在上查询一个定义在的属性会先在上查找如果没有查到那么会顺着原型链去查找所以以下判别式均为如果我们做如下操作原型链并没有被访问一个新的会被加入到的属性中去新的 原文发自我的博客 xiaoyu2er.github.io 易企秀招聘啦! JavaScript Prototypal Inheritance 首先...
摘要:深入之继承的多种方式和优缺点深入系列第十五篇,讲解各种继承方式和优缺点。对于解释型语言例如来说,通过词法分析语法分析语法树,就可以开始解释执行了。 JavaScript深入之继承的多种方式和优缺点 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎,再让我...
阅读 2744·2021-11-19 09:40
阅读 5293·2021-09-27 14:10
阅读 2098·2021-09-04 16:45
阅读 1461·2021-07-25 21:37
阅读 2993·2019-08-30 10:57
阅读 2980·2019-08-28 17:59
阅读 1054·2019-08-26 13:46
阅读 1406·2019-08-26 13:27