JavaScript知识点整理

JavaScript是按照ECMAScript标准设计和实现的,后文说的JavaScript语法其实是ES5的标准的实现。

先说说有哪些基础语法?

最基础语法有哪些?

基础语法几乎所有的语言差异不大,无非数据类型、操作符、控制语句、函数等,简单列举下。

5种基本数据类型 & 1种复杂的数据类型

JavaScript包含5种基本数据类型,分别是undefined / null / boolean / number / string,基本数据类型就这五种,没有其他的!

JavaScript包含1种复杂的数据类型,就是Object类型,Object类型是所有其他对象的基类。

注意:JavaScript并不区分浮点数和整数,都是用number来表示。

前面提到的5种基本数据类型,以及这儿的1种复杂数据类型,这就是数据类型的全部了!

基本操作符

这个是常识,知道怎么回事就好。

常用的操作符包括:算术操作符、关系操作符、布尔操作符、赋值操作符等。

控制语句

这就是我们常说的if-else之类的控制语句。

常用的并不多:if语句、switch语句、for语句、while语句、for-in语句。

函数

函数就是一小段逻辑的封装,理论上逻辑越独立越好。

JavaScript函数相对其他语言来说有很大不同。JavaScript函数既可以作为参数,也可以作为返回值。

此外JavaScript函数可以接受任意数量的参数,并且可以通过arguments对象来访问这些参数。

任何一门语言的基础语法都是相通的,除开一些细节差异,大致就是上面这些了:数据类型、操作符、控制语句、函数、模块等等。

接下来介绍稍微复杂的一些概念。

变量、作用域、内存问题

变量

JavaScript变量分为两种:基本类型和引用类型。其中基本类型就是前面提到的5种基本数据类型,引用类型就是前面提到的Object以及基于它的其他复杂数据类型。

  • 基本类型:在内存中占据实际大小的空间,赋值的时候,会在内存中创建一份新的副本。保存在栈内存中。
  • 引用类型:指向对象的指针而不是对象本身,赋值的时候,只是创建了一个新的指针指向对象。保存在堆内存中。


变量内存分配

一句话就是,基本类型在内存中是实际的值;而引用类型在内存中就是一个指针,指向一个对象,多个引用类型可能同时指向同一个对象。

那么,如何确定某个变量是哪种数据类型呢?

确定一个变量是哪种基本类型用typeof操作符。

确定一个变量是哪种引用类型用instanceof操作符。

这个别忘了!

作用域

变量是在某个特定的作用域中声明的,作用域决定了这些变量的生命周期,以及哪些代码可以访问其中的变量。

JavaScript作用域只包括全局作用域和函数作用域,并不包含块级作用域!

作用域是可以嵌套的,从而形成作用域链。由于作用域链的存在,可以让变量的查找向上追溯,即子函数可以访问父函数的作用域=>祖先函数的作用域=>直到全局作用域,这种函数我们也称为闭包,后文会介绍。

如下图所示,每个作用域能够访问到的变量以及嵌套的作用域可向上追溯。


作用域链

作用域的概念看着简单,实际使用会有不少问题,遇到问题要细心分析。

内存问题

JavaScript引擎具有自动垃圾回收机制,不需要太关注内存分配和垃圾回收问题。这儿就不展开了!

引用类型

前面提过,Object是唯一的复杂数据类型,引用类型都是从Object类型上继承而来。

  • Array:数组类型
  • Date:日期类型
  • RegExp:正则表达式类型,这个多学学有好处!
  • 等等...

那问题来了,我们用的最多的函数是什么数据类型呢?答案是Function类型!

诶,好像发现了点什么东西?由于Function是引用类型,而JavaScript又可以往引用类型上加属性和方法。那么,函数也可以!这也是JavaScript函数强大和复杂的地方。也就是说:函数也可以拥有自定义方法和属性!

此外,JavaScript对前面提到的5种基本类型的其中3种也做了引用类型封装,分别是Boolean、Number、String,但其实使用不多,了解就行。

对了,在所有代码执行之前,作用域就内置了两个对象,分别是Global和Math,其中浏览器的Global就是window啦!

到此为止,JavaScript中基础的概念都差不多介绍了,其中函数和作用域相对来说复杂一些,其他的都比较浅显。

接下来,我会介绍介绍JavaScript中一些稍微复杂一些的概念:面向对象。

面向对象编程

JavaScript本身并没有类和接口的概念了,面向对象都是基于原型实现的。

为了简单,我们只分析面向对象的两个问题:

  • 如何定义一个类?
  • 如何实现类的继承

定义一个类

不扯其他的,直接告诉你。我们使用构造函数+原型的方式来定义一个类。

使用构造函数创建自定义类型,然后使用new操作符来创建类的实例,但是构造函数上的方法和属性在每个示例上都存在,不能共享,于是我们引入原型来实现方法和属性的共享。


原型

最后,我们将需要共享的方法和属性定义在原型上,把专属于实例的方法和属性放到构造函数中。到这儿,我们就通过构造函数+原型的方式定义了一个类。

实现继承

前文讲了如何定义一个类,那么我们定义一个父类,一个子类。

如何让子类继承父类呢?不扯别的,直接告诉你。JavaScript通过原型链来实现继承!

如何构建原型链呢?将子类实例赋值给父类构造函数的原型即可。好绕,但是千万得记住了!


原型链继承

构建原型链之后,子类就可以访问父类的所有属性和方法!

面向对象的知识可以用一本书来写,这儿只是简单的介绍下最基础最常用的概念。

函数表达式

JavaScript中有两种定义函数的方式:函数声明和函数表达式。

使用函数表达式无须对函数命名,从而实现动态编程,也即匿名函数。有了匿名函数,JavaScript函数有了更强大的用处。

递归

递归是一种很常见的算法,经典例子就是斐波拉契数列。也不扯其他的,直接说递归的最佳实践,上代码:

递归就是这样,好多人还在使用arguments.callee的方式,改回函数表达式的方式吧,这才是最佳实践。

啰嗦一句,好多人觉得递归难写,其实你将其分为两个步骤就会清晰很多了。

  • 边界条件,通常是if-else。
  • 递归调用。

按这个模式,找几个经典的递归练练手,就熟悉了。

闭包

很多人经常觉得闭包很复杂,很容易掉到坑里,其实不然。

那么闭包是什么呢?如果一个函数可以访问另一个函数作用域中的变量,那么前者就是闭包。由于JavaScript函数可以返回函数,自然,创建闭包的常用方式就是在一个函数内部创建另一个函数!

这并没有什么神奇的,在父函数中定义子函数就可以创建闭包,而子函数可以访问父函数的作用域。

我们通常是因为被闭包坑了,才会被闭包吓到,尤其是面试题里一堆闭包。

闭包的定义前面提了,如何创建闭包也说了,那么我们说说闭包的缺陷以及如何解决?


  1. /* 我们通过subFuncs返回函数数组,然后分别调用执行 */  
  2. // 返回函数的数组subFuncs,而这些函数对superFunc的变量有引用  
  3. // 这就是一个典型的闭包  
  4. // 那么有什么问题呢?  
  5. // 当我们回头执行subFuncs中的函数的时候,我们得到的i其实一直都是10,为什么?  
  6. // 因为当我们返回subFuncs之后,superFunc中的i=10  
  7. // 所以当执行subFuncs中的函数的时候,输出i都为10。  
  8. //  
  9. // 以上,就是闭包最大的坑,一句话理解就是: 
  10. // 子函数对父函数变量的引用,是父函数运行结束之后的变量的状态  
  11. function superFunc() {  
  12. var subFuncs = new Array();  
  13. for (var i = 0; i < 10; i++) {  
  14. subFuncs[i] = function() {  
  15. return i;  
  16. };  
  17. }  
  18. return subFuncs;  
  19. }  
  20. // 那么,如何解决上诉的闭包坑呢?  
  21. // 其实原理很简单,既然闭包坑的本质是:子函数对父函数变量的引用,是父函数运行结束之后的变量的状态  
  22. // 那么我们解决这个问题的方式就是:子函数对父函数变量的引用,使用运行时的状态  
  23. // 如何做呢?  
  24. // 在函数表达式的基础上,加上自执行即可。  
  25. function superFunc() {  
  26. var subFuncs = new Array();  
  27. for (var i = 0; i < 10; i++) {  
  28. subFuncs[i] = function(num) {  
  29. return function() {  
  30. return num;  
  31. };  
  32. }(i);  
  33. }  
  34. return subFuncs; 
  35.  

综上,闭包本身不是什么复杂的机制,就是子函数可以访问父函数的作用域。

而由于JavaScript函数的特殊性,我们可以返回函数,如果我们将作为闭包的函数返回,那么该函数引用的父函数变量是父函数运行结束之后的状态,而不是运行时的状态,这便是闭包最大的坑。而为了解决这个坑,我们常用的方式就是让函数表达式自执行。

此外,由于闭包引用了祖先函数的作用域,所以滥用闭包会有内存问题。

好像把闭包说得一无是处,那么闭包有什么用处呢?

主要是封装吧...

封装

闭包可以封装私有变量或者封装块级作用域。

封装块级作用域

JavaScript并没有块级作用域的概念,只有全局作用域和函数作用域,那么如果想要创建块级作用域的话,我们可以通过闭包来模拟。

创建并立即调用一个函数,就可以封装一个块级作用域。该函数可以立即执行其中的代码,内部变量执行结束就会被立即销毁。

封装私有变量

JavaScript也没有私有变量的概念,我们也可以使用闭包来实现公有方法,通过隐藏变量暴露方法的方式来实现封装私有变量。

总结说点啥?

这差不多就是JavaScript的一些基础语法和稍微高级一些的用法,其实所谓的高级,都是JavaScript“不太成熟”的表现,尤其是面向对象,出于工程化的需要但是JavaScript本身并不完美支持。好在ES6最新标准解决了很多问题,结合Babel用起来也不用太考虑兼容性问题,如果你是新手的话,建议你直接去撸ES6+Babel吧。

  • JavaScript的基础主要包括:5中基本数据类型、1种复杂的数据类型、操作符、控制语句、函数等。
  • 了解基本的语法后,你还需要学习学习JavaScript的变量、作用域、作用域链。
  • 常见的引用类型可以边查边用。作为过来人,建议多学学正则,对你的代码功底会有较大的提升。
  • 面向对象编程的部分外面有很多种方式,你只需要记住使用构造函数+原型去定义一个类,使用原型链去实现继承即可。更多的扩展,去翻翻书吧。
  • 函数表达式引出了几个比较好玩的东西:递归、闭包、封装。记住递归的最佳实践、闭包的定义及缺陷、闭包的适用场景。

JavaScript作为一门动态语言,和其他语言有较大的差异,这也造成很多人学习JavaScript时会觉得难学。但你现在看看前文,虽然是一个简略的总结,但JavaScript主要的内容就这些了,所以不要被自己吓到了。

再补一句,如果你是新手的话,建议你直接去撸ES6+Babel吧。

作者:齐修

来源:51CTO

时间: 2024-08-04 09:12:51

JavaScript知识点整理的相关文章

JavaScript知识点整理_javascript技巧

JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能. 首先,还是用比较官方的文字描述来解释下JavaScript: JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型. 它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于

常见的JavaScript易错知识点整理

前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES6的知识点. JavaScript知识点 1.变量作用域 var a = 1;  function test() {      var a = 2;      console.log(a); // 2  }  test();  上方的函数作用域中声明并赋值了a,且在console之上,所以遵循

JavaScript易错知识点整理_javascript技巧

前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一些ES6的知识点. JavaScript知识点 1.变量作用域 var a = 1; function test() { var a = 2; console.log(a); // 2 } test(); 上方的函数作用域中声明并赋值了a,且在console之上,所以遵循就近原则输出a等于2. va

Lua中的函数相关知识点整理汇总

  这篇文章主要介绍了Lua中的函数相关知识点整理汇总,包括函数的参数传递和定义函数等基本知识,需要的朋友可以参考下 函数是一组一起执行任务的语句.可以把代码放到独立的函数中.怎么划分代码功能之间的不同,但在逻辑上划分通常是让每个函数执行特定的任务. Lua语言提供了程序可以调用大量的内置方法.例如,方法print()打印作为输入传参数在控制台中. 函数是已知的各种名称,如方法或子程序或程序等. 定义一个函数 在Lua编程语言中的方法的定义一般形式如下: 代码如下: optional_funct

JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解_javascript技巧

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什么,有什么用,今天在网上看到了一篇讲JavaScript闭包的文章(原文链接),讲得非常好,这下算是彻底明白了JavaScript的闭包到底是个神马东东以及闭包的用途了,在此写出来和大家分享一下,希望不理解JavaScript闭包的朋友们看了之后能够理解闭包!以下内容大部分是来自原文,我在原文的基础

JavaScript知识点总结(十一)之js中的Object类详解_javascript技巧

JavaScript中的Object对象,是JS中所有对象的基类,也就是说JS中的所有对象都是由Object对象衍生的.Object对象主要用于将任意数据封装成对象形式. 一.Object类介绍 Object类是所有JavaScript类的基类(父类),提供了一种创建自定义对象的简单方式,不再需要程序员定义构造函数. 二.Object类主要属性 1.constructor:对象的构造函数. 2.prototype:获得类的prototype对象,static性质. 三.Object类主要方法 1

JavaScript知识点总结(十)之this关键字_javascript技巧

this是Javascript语言的一个关键字.随着函数使用场合的不同,this的值会发生变化.但是有一个总的原则,那就是this指的是,调用函数的那个对象.JavaScript中的this指针是一个动态的变量,一个方法内的this指针并不是始终指向定义该方法的对象的.Javascript中this关键字通常指向当前函数的拥有者. 下面通过代码给大家介绍下.具体代码如下所示: <script type="text/javascript"> function Person()

JavaScript知识点总结(六)之JavaScript判断变量数据类型_javascript技巧

最近做了一个项目,其中有关于js判断数据类型的处理,在网上搜了相关资料,并且亲自测试了各种数据类型的判断,绝对安全.下面小编把具体内容总结分享给大家,大家参考下! 一.JS中的数据类型 1.数值型(Number):包括整数.浮点数. 2.布尔型(Boolean) 3.字符串型(String) 4.对象(Object) 5.数组(Array) 6.空值(Null) 7.未定义(Undefined) 二.判断一个变量的数据类型 1.数值型(number) 比较常用的判断方法是: function i

JavaScript知识点总结(五)之Javascript中两个等于号(==)和三个等于号(===)的区别_javascript技巧

一.JavaScript"=="的作用 1.当==两边的内容是字符串时,则比较字符串的内容是否相等. 2.当==两边的内容是数字时,则比较数字的大小是否相等. 3.当==两边的内容是对象或者是对象的函数属性时,则比较内存地址是否相等. 二.==和===的区别 ==用于一般比较,===用于严格比较,==在比较的时候可以转换数据类型,===严格比较,只要类型不匹配就返回flase. 举例说明: <script type="text/javascript">