我的JS体系整理(二)

一. evalhtml

  eval()函数计算JavaScript字符串,并把它做为脚本代码来执行。若是参数是一个表达式,eval()函数将执行表达式。若是参数是Javascript语句,eval()将执行Javascript语句。前端

1.1java

  如上图所示,第一个eval内部为一个函数表达式,在执行该函数的同时,定义了两个全局变量XY,因此结果分别为200427数组

  因为由于它会执行任意传给它的代码,在代码字符串未知或者是来自一个不信任的源时,会致使安全问题,同时很是耗性能(它会执行两次2次,一次解析成js语句,一次执行),最重要的是,99.9%使用eval 的场景都有不使用eval的解决方案,因此在任何状况下咱们都应该避免使用eval函数。浏览器

二. nullundefined 的区别缓存

  (1) null表示一个对象是“没有值”的值,也就是值为“空”;undefined表示一个变量声明了没有初始化(即没有赋值)安全

  (2) undefined不是一个有效的JSON,而null是;undefined的类型(typeof)undefined,而null的类型(typeof)object闭包

  (3) 在验证null时,必定要使用“===” ,由于“==”没法分别nullundefined!app

图2.1函数

三. 事件与事件流

  (1) 事件

  事件是文档或者浏览器窗口中发生的,特定的交互瞬间,也能够理解为是用户或浏览器自身执行的某种动做,如click,changehover都是事件的名字,同时事件是javaScriptDOM之间交互的桥梁。

  (2) 事件流

  事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所通过的全部节点都会收到该事件,这个传播过程即DOM事件流。事件流有两种模型,即捕获型事件流和冒泡型事件流。

  冒泡型事件流:事件的传播是从最特定的事件目标到最不特定的事件目标。即从DOM树的叶子到根。

  捕获型事件流:事件的传播是从最不特定的事件目标到最特定的事件目标。即从DOM树的根到叶子。

3.1

  如上图所示,DOM标准采用捕获+冒泡,两种事件流都会触发DOM的全部对象,从document对象开始,也在document对象结束。DOM标准规定事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。

  (1) 事件捕获阶段:实际目标(<div>)在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到<html>再到<body>就中止了。

  (2) 处于目标阶段:事件在<div>上发生并处理。可是事件处理会被当作是冒泡阶段的一部分。

  (3) 冒泡阶段:事件又传播回文档。

  来个例子搞一下,以下图:

3.2

  上图点击btn1的区域,会先弹出“btn1”,紧跟着弹出“content”,这就是一个最典型的冒泡事件。

3.3

  上图代码运行结果为:先弹出“btn1”,而后弹出“btn2”,最后弹出“content ”。它与前一个代码的区别是,一个是绑定,一个是注册。即DOM元素只能绑定一个事件,相似变量,后面的会把前面的覆盖掉;可是DOM元素能够注册多个事件,即在注册第一个事件的时候,同时注册了第二个事件,因此在执行的时候,会从第二个(也就是当前元素的最后一个注册事件)开始执行,直到执行完第三个事件。

四. 闭包

  闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(一般是一个函数)于是,这些变量也是该表达式的一部分。闭包的特色以下:

  1. 做为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  2.   2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。

  简单的说,Javascript容许使用内部函数即函数定义和函数表达式位于另外一个函数的函数体内。并且,这些内部函数能够访问它们所在的外部函数中声明的全部局部变量、参数和声明的其余内部函数。当其中一个这样的内部函数在包含它们的外部函数以外被调用时,就会造成闭包。

图4.1

  如上图所示,给函数原型增长一个方法,同时建立一个实例,会获得结果3.14159

  4.2

  上图就是把一个函数return为一个变量,那么当建立该函数的实例的时候,全部该变量具备的方法均可以被调用,同时仍是在函数做用域以外被调用,即闭包,结果依旧为3.14159

图4.3

这属于最容易理解的方式,即直接new一个对象,给它赋予各类属性和方法,最终结果依旧为3.14159

4.4

  这种方式是使用最多的一种方式,也是最方便的一种方式。(var obj = {}就是声明一个空的对象。

  闭包的用途以下:

  1. 函数只须要执行一次,其内部变量无需维护,好比UI的初始化
  2. 前端缓存。假设有一个很耗性能和时间的函数对象,每次调用都须要好久的时间,那么咱们就须要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,若是找不到,则进行计算,而后更新缓存并返回值,若是找到了,直接返回查找到的值便可。闭包正是能够作到这一点,由于它不会释放外部的引用,从而函数内部的值能够得以保留。
  3. 封装函数(组件化)
  4. 实现类和继承(参考第一种写法)

五. callapply

  1. 共同点

  都能够用来代替另外一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象

  1. 不一样点

  applyapply(thisObj[argArray])最多只能有两个参数——this对象和一个数组argArray。若是给该方法传递多个参数,则把参数都写进这个数组里面,固然,即便只有一个参数,也要写进数组里。若是argArray不是一个有效的数组或arguments对象,那么将致使一个TypeError。若是没有提供argArraythisObj任何一个参数,那么Global对象将被用做thisObj,而且没法被传递任何参数。

  callcall(thisObjObject)它能够接受多个参数,第一个参数与apply同样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊状况下须要改变this指针。若是没有提供thisObj参数,那么 Global 对象被用做thisObj

5.1

  如上图所示,不管是apply仍是call,它的结果都是同样的,都是调用的前面的函数的方法,可是传的参数是不同的,固然这只是在参数方面的不一样。

5.2

  如上,就是利用callapply实现继承,经过给函数赋予属性和方法,而后给另外一个函数继承原函数,再建立新函数的实例,就实现了最简单的继承。

  图5.3

  如上图所示,即一种多重继承的实现方式。

相关文章
相关标签/搜索