JS核心概念
Javascript本质第一篇:核心概念
很多人在使用Javascript之前都至少使用过C++、C#或Java,面向对象的编程思想已经根深蒂固,恰好Javascript在语法上借鉴了Java,虽然方便了Javascript的入门,但要深入理解Javascript的时候,却带来了误导。作者在学习Javascript的时候曾陷入了这个误区,希望通过这篇文章让新学者避免走这个弯路,迅速正确地掌握Javascript。
1. 要点
在面对Javascript时,要牢记以下几点:
1.1 Javascript不是面向对象的编程语言
如果非要把Javascript归到面向什么的话,Javascript准确的说是面向原型的编程语言,从self编程语言发展而来,除了语法上借鉴Java,和Java什么关系都没有,本质上也不同。简单说,Javascript里面没有类,全是对象。在使用Javascript的时候,应该时刻提醒自己:Javascript不是C++、C#或Java。
1.2 Javascript是解释执行的语言
虽然这很显而易见,但如果不时刻牢记这一点,而把Javascript和编译型语言的运行方式混淆的话,也非常不利于理解Javascript。比如,如果你用C++、C#或Java中的局部变量的思想去理解Javascript函数中通过var定义的变量的话,就会有麻烦。
2. Javascript中的对象和类型
Javascript有Undefined, Null, Boolean, Number, String, Object和Function这几种类型,但本质上Javascript中所有类型的对象都只是对象,都有共同的原型:一个内建的Object对象。只不过Javascript运行时对Undefined, Null, Boolean, Number, and String这五种基础类型的对象以及Function类型的函数对象以特定的方式解释和处理。
Javascript中的对象是键值对的集合,键的类型是字符串,值可以是任意对象。可以通过new 函数()来创建新对象,也可以通过{}语法来创建新对象。
函数也是对象,是一种包含可运行的代码的特殊对象,并且代码能够以函数调用的形式被执行。函数对象能通过function关键字定义或通过new关键字使用Function构造函数来创建。
下面的示例创建了一个函数对象foo,并为它设置三个属性:一个数字,一个字符串,一个函数。从示例可以看到函数对象除了能被调用以外,其他行为和普通对象无异。
函数可以作为构造函数通过new关键字来创建对象,在Javascript中,通常将构造函数称为对象的类型。比如obj = new Fun(),那么称obj的类型为Fun。
比如前面提到的函数对象创建的方法之一:fun = new Function("参数", "函数体"),Function本身是一个Javascript内建的函数。同理Boolean, Number, String, Object, Array, Date等都是内建的函数。没有内建的Undefined和Null函数,Undefined和Null类型都只有内建的唯一的对象,分别是undefined和null。
3. 执行上下文
Javascript中每一行代码的执行都是在当前执行上下文中完成。
执行上下文的层级关系是由代码的定义结构(也就是源代码字面结构)决定的,与运行时函数的调用栈结构无关。
执行上下文由一个上下文变量容器和一个this绑定构成。上下文变量容器中包含当前执行上下文中定义的变量。this绑定表示当前执行上下文中this关键字指向的对象。
简单来说,每次函数调用都进入一个新的执行上下文,同一函数递的归调用也会进入新的执行上下文。
每一个执行上下文都包含对创建它的上一级执行上下文的引用,因此所有执行上下文组成一棵树。
在浏览器中,根执行上下文(即不在任何函数中运行的代码)中没有上下文变量容器,this绑定到全局对象window。因此在根执行上下文中定义变量时,使用var、不使用var和使用this.定义的变量都是全局对象window的属性,因为没有上下文变量容器。通过这一规定,Javascript运行过程中的所有执行上下文都能指向全局对象,形成一棵完整的树。
在除了根执行上下文之外的其它执行上下文中,变量定义的规则如下:
var i = 1 | 变量i位于当前执行上下文的上下文变量容器中 |
j = 2 | 变量j是全局对象的属性 |
this.k = 3 | 变量k是当前执行上下文的this对象的属性 |
在表达式中使用一个变量时,Javascript将首先从当前执行上下文的上下文变量容器中查找该变量,如果不存在,则在上级执行上下文的上下文变量容器中查找,以此类推,直到根执行上下文,在根执行上下文中,将在全局对象中查找是否有同名的属性。示例如下:
当前执行上下文的this绑定默认继承自上级执行上下文,如果当前运行代码所在的函数是通过obj.currentfun()的方式调用,也就是obj对象的方法,那么this将被绑定到obj。在使用时,this关键字必须明确写出,因为this在逻辑上是与执行上下文有关的,与当前函数所属的对象没有直接因果关系。
垃圾回收机制:如果当前执行上下文及其中的代码已经执行完成,且其所有下级执行上下文已经释放,且没有来自当前执行上下文之外的对当前执行上下文的上下文变量容器中的变量的引用,那么当前执行上下文被释放,当前执行上下文的上下文变量容器中的变量指向的对象和this指向的对象的引用值减一(各引擎具体实现不同,这里描述的是原理)。
这也就是Javascript中常用到的闭包模式的原理。如果从传统面向对象语言的角度去看,闭包模式看上去很诡异;但是在理解了Javascript的执行上下文后,闭包模式就是一种很自然的代码编写模式。
4. 原型
由于Javascript中没有类的概念,因此也没有面向对象中的继承的概念。在完全没有任何继承机制的编程语言中,每个对象的方法都要明确设置一遍。假如Javascript没有继承机制,通过构造函数function A(name) {this.name= name;};创建了100个A的对象, 现在要为每个对象实现一个新的方法,就需要明确的为这100个对象都添加一个方法属性,当每个对象都有很多方法的时候,会带来巨大的性能开销和非常差的编码体验,使得代码编写方式最终会倒退到面向过程的方式。
实际上,Javascript从发展的最初就定位为面向原型的编程语言,通过原型实现另一种方式的继承:属性共享。如果为了和面向对象中的继承区分,Javascript中通过原型实现的应该叫做共享。
Javascript中的原型也是一个对象;原型这个词也表示一种机制。
每个对象都可以拥有一个原型,同时这个原型本身还可以有自己的原型,形成一个原型链,直到其原型为null的原型。
当获取对象的一个属性时,先在当前对象的键值对集合中查找,如果找到返回对应的值;如果没有,则在原型对象的键值对集合中查找,如果还没找到,则在原型的原型中查找,以此类推。
通过一个示例来演示原型的使用方法:
上面例子中,PersonPrototype就是原型对象,Person是构造函数,将Person的prototype属性设置为PersonPrototype对象,那么通过new Person创建的所有对象的原型都是PersonPrototype。
通过示例可以看到,修改原型中showMyName方法的定义,p.showMyName()的输出也会跟着发生变化,这个现象和上面原型的定义一致。
如果明确的为对象p设置一个showMyName方法,那么p对象的键值对集合中将也包含showMyName的定义,根据上面规则的描述的规则,p对象中定义的showMyName将被使用,忽略了原型中对showMyName的定义。这个时候,我们可以通过p.__proto__.showMyName来访问原型中的showMyName方法,但是调用p.__proto__.showMyName的时候,this关键字绑定到了原型对象PersonPrototype,由于原型对象中没有name属性的定义,因此输出“undefined!”。
接下来再定义几个Person对象:
相信上面代码的输出都不难理解了,所有Person对象都共享了原型对象的方法,除非某个Person对象中重新定义了原型中的方法。
一般来说原型对象中通常定义方法和常量,定义对象的状态值没有意义,因为多数情况下所有的对象共享一个状态值没有实际意义。
5. 结论
本文介绍了Javascript的三个核心概念:对象、执行上下文和原型。这些是Javascript最重要的内容,理解这三点之后,很快就能掌握Javascript。
Javascript代码中各类表达式与C++基本相同。
Javascript包括很多预定义的类型、对象和对象属性,比如全局对象及其属性,JSON类型和RegExp类型等等,这些查阅手册即可。
当然还有很多细节性的东西需要进一步讨论,例如:如果不明确设置Person的原型,该原型默认会是一个Person类型的对象,还有constructor属性的理解也都有一些绕。有机会将在后续章节中展开讨论。
JS核心概念的更多相关文章
- Vue.js核心概念
# 1. Vue.js是什么? 1). 一位华裔前Google工程师(尤雨溪)开发的前端js库 2). 作用: 动态构建用户界面 3). 特点: * 遵循MVVM模式 * 编码简洁, 体积小, 运行效 ...
- TensorFlow.js之安装与核心概念
TensorFlow.js是通过WebGL加速.基于浏览器的机器学习js框架.通过tensorflow.js,我们可以在浏览器中开发机器学习.运行现有的模型或者重新训练现有的模型. 一.安装 ...
- Ext JS 6学习文档–第2章–核心概念
核心概念 在下一章我们会构建一个示例项目,而在这之前,你需要学习一些在 Ext JS 中的核心概念,这有助于你更容易理解示例项目.这一章我们将学习以下知识点: 类系统,创建和扩展类 事件 Ext JS ...
- js沉思录一:js的核心概念
js的核心概念: 原型.对象(Object).函数(Function); 原型:路由路径上非叶子结点的对象: 对象:无序属性(包括函数)的集合: 函数:函数上下文的集合: 原型: 原型的创建.指定.修 ...
- [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)
本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...
- Angularjs -- 核心概念
angularjs旨在减轻使用AJAX开发应用程序的复杂度,使得程序的创建.測试.扩展和维护变得easy.以下是angularjs中的一些核心概念. 1. client模板 多页面的应用通 ...
- webpack的四个核心概念介绍
前言 webpack 是一个当下最流行的前端资源的模块打包器.当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后 ...
- webpack核心概念
一.webpack四个核心概念 1.入口[Entry] webpack将创建所有应用程序 依赖关系图表.图表的起点被称之为 入口起点.入口起点告诉webpack从哪里开始,并遵循着依赖关系图表知道打包 ...
- Redux 核心概念
http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...
随机推荐
- java-新浪微博开放平台——话题跟踪
代码 网盘地址:http://pan.baidu.com/s/1pJ1D0Kz
- 【百度地图API】建立全国银行位置查询系统(五)——如何更改百度地图的信息窗口内容?
原文:[百度地图API]建立全国银行位置查询系统(五)--如何更改百度地图的信息窗口内容? 摘要: 酷讯.搜房.去哪儿网等大型房产.旅游酒店网站,用的是百度的数据库,却显示了自定义的信息窗口内容,这是 ...
- 加快XCode编译链接速度(200%+)—XCode编译慢液
最近在一个大型项目的开发的时候遇到一个很头疼的问题,由于该项目的代码更,每次建立联系1纪要.浪费时间调试.因此,一些研究如何提高编译链接速度,这里给大家分享. 为了提高编译和链接的是以下三种方式的速度 ...
- HHVM Installation and Configuration(HHVM 安装及配置)
Installation and Configuration¶ General Installation Considerations Installation on Linux systems Ub ...
- MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证
原文:MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证 MVC中,关于往后台提交的方法有: 1.Html.BeginForm():同步 2.Ajax.BeginForm():异 ...
- C语言双向链表
原文:C语言双向链表 今天写了点双向链表的各种操作,写插入的时候费了点时间,不过,现在看来还是值得耗费那点时间去写的,这种小东西应该能信手拈来才行啊. /*双向链表*/ #include <st ...
- s2sh三大框架整合过程(仅供参考)
三大框架顾名思义就是非常有名的Struts2 ,Hibernate,Spring, 框架整合的方法很多,现在我写一个非常简单的整合过程,相信大家一看就会! 这里使用的struts-2.2.1.1.hi ...
- ZOJ 2109 FatMouse' Trade (背包 dp + 贪婪)
链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1109 FatMouse prepared M pounds of cat ...
- Spring之SpringMVC的MethodNameResolver(源码)分析
前言 在介绍SpringMVC 的Controller的具体实现中,我们讲到了MultiActionController.在获取处理请求对于的方法的时候我们用到了下面的代码,来自于MultiActi ...
- 项目笔记---CSharp图片处理
原文:项目笔记---CSharp图片处理 项目笔记---CSharp图片处理 最近由于项目上需要对图片进行二值化处理,就学习了相关的图片处理上的知识,从开始的二值化的意义到动态阀值检测二值化等等,并用 ...