文档章节

浅谈JS中的原型与作用域

SupKylin
 SupKylin
发布于 2016/11/07 11:58
字数 1356
阅读 125
收藏 0

        最近在和其他的小伙伴交流的过程中,发现虽然现在Web的各种JS库种类繁多,但是很多人在使用的时候,只知道如何去使用,却对内部的一些封装原理并不是很清楚,所以动了写一片这样的博客的心思。

       

        在我们工作中则也少不了各类函数封装,而在多人进行协同开发的时候,打个比方我们需要面对的一个很直接的问题就是全局污染的问题。而如果很好的理解了作用域和原型链的概念,则可以很轻松的去避免这些情况的发生。

        首先,什么是原型,原型的概念是什么,其实现在市面上的各类JS库,以Jquery为例,使用面向对象编程思想对各类方法等进行封装,而个人认为,在JS的面向对象中,最重要的思想即是作用域与原型链。

        那么,什么是原型。

        其实简单来说,原型就是一个构造函数的“prototype”。

        在使用面向对象思想编程的时候,我们通常是使用一个构造函数来去“new”一个对象,而我们可以通过“this.属性”的方式给他添加一些方法,那么通过这个构造函数创建出来的对象都具有了这些属性和方法,但是这样做有一些什么样的缺点呢?

        其实他的缺点是在我们复用这个构造函数的时候,会大量的浪费内存,因为构造函数中的属性和方法,会在调用的时候被处理,每一个“new”出来的对象,都是一个单独的副本,“new”一个对象,则占用一份内存,但是对于这个构造函数中的各种方法来说,每个对象都应该是相同的,被共享的。

        那么,如何去解决这个问题,这个时候,原型的作用就被引申出来了。

        在每一个构造函数中,都有一个“prototype”属性,只要是通过这个构造函数创建出来的对象,都可以访问的到这个构造函数中的“prototype”中的各种属性和方法,我们可以通过这个属性去实现继承,从而也解决了上面所说的问题。

        而在每一个对象中,又都存在一个“__proto__”属性,只不过这个属性是一个非标准的属性,所以为了区分,我们将“构造函数.prototype”叫做对象的原型属性,将“对象.__proto__”叫做对象的原型对象。

        其实他们指向的是同一个对象,只不过是从不同的角度来看待这个对象,“__proto__”是从对象的角度来看,而“prototype”则是从构造函数的角度来看待,如果输入“构造函数.prototype===对象.__proto__”的时候,你会发现他返回的是一个“true”。

        注意:在“prototype”属性中,它本身自带的一个属性“constructor”指向的是这个构造函数的本身。

        那么关于函数原型链,我这里还有几条结论:

            1、对象都有原型对象,对象默认继承自原型对象

            2、函数被定义后,默认就有“prototype”,原型属性也是对象。

            3、函数的原型默认继承自“Object.prototype”

            4、所有的函数都是“Function”的实例,也就是说,函数(作为对象)都继承子“Function.prototype”

            5、函数也是一个对象。

        然后这里再放上一张图供参考:

        

 

        说完了原型,再来谈谈作用域、

        在JS中,我们并没有其他语言中的那种块级作用域的概念,只有两个作用域,一个是整个“script”标签的全局作用域,一个是函数内部的词法作用域。

        我们在书写代码的时候,打个比方你书写了一个表达式,他需要去当前作用域内去寻找他所需要的变量,如果你没有定义这个变量,则会报错,如果你书写的变量在他的下级作用域,他也会报错,在这里,我们就可以去很好的理解作用域的概念。

        在JS中,变量的搜索原则是他会先去自己本身所在的作用域中去寻找需要的变量,如果没找到,则去上级作用域寻找,一直找到全局作用域,如果还没找到,则会报错,而且内部作用域可以访问到外部,但是外部无法访问到内部。

        所以在以Jquery为例,它使用了原型链来对各类的方法和函数进行继承,然后使用一个自调用函数实现作用域的包裹,最终的Window作为一个参数传入进去,然后将“$”与“jquery”作为window的属性曝露出去,这样就实现了我们能够在全局去调用这个“$”函数或者是“jquery”函数。

        注意:在JS中,还存在变量的提升和函数的提升,在JS的预解析阶段,会将我们在这个作用域中声明的所有变量与函数,首先提升到当前作用域的最顶层,然后在去一步步执行代码。

 

        

© 著作权归作者所有

SupKylin
粉丝 0
博文 8
码字总数 5094
作品 0
虹口
程序员
私信 提问
细说JavaScript数据类型及转换

细说JavaScript数据类型及转换 JavaScript数据类型 1.Boolean(布尔) 布尔:(值类型)var b1=true;//布尔类型 2.Number(数字) 数值:(值类型)var n1=3.1415926;//数值类型 n1.toFixed...

开元中国2015
2015/07/13
0
0
每个JavaScript工程师都应懂的33个概念

摘要: 基础很重要啊! 原文:33 concepts every JavaScript developer should know 译文:每个 JavaScript 工程师都应懂的33个概念 作者:stephentian Fundebug经授权转载,版权归原作者所有...

Fundebug
2018/10/30
0
0
JavaScript开发者应懂的33个概念

简介 这个项目是为了帮助开发者掌握 JavaScript 概念而创立的。它不是必备,但在未来学习(JavaScript)中,可以作为一篇指南。 本篇文章是参照 @leonardomso 创立,英文版项目地址在这里。 ...

大灰狼的小绵羊哥哥
2018/10/22
0
0
《前端面试手记》之JavaScript基础知识梳理(下)

👇 内容速览 👇 实现ES5继承的4种方法 原型和原型链 作用域和作用域链 Event Loop 执行上下文 闭包的理解和分析 🔍查看全部教程 / 阅读原文🔍 ES5继承 题目:ES5中常用继承方法。 方...

godbmw
04/03
0
0
浅谈Javascript模块化开发

*** 自己接触过的几种javascript模块开发,由于水平有限,只能简单谈一谈。 *** 立即执行匿名函数 由于javascript的函数作用域,将模块代码放入立即执行匿名函数中,防止污染全局变量。将需要...

jackzlz
2015/08/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AI实战】手把手教你深度学习文字识别(文字检测篇:基于MSER, CTPN, SegLink, EAST等方法)

文字检测是文字识别过程中的一个非常重要的环节,文字检测的主要目标是将图片中的文字区域位置检测出来,以便于进行后面的文字识别,只有找到了文本所在区域,才能对其内容进行识别。 文字检...

雪饼
今天
6
0
思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
今天
10
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
6
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
8
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
13
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部