JavaScript总结

1.JavaScript简介

1.1 javascript的组成部分

(1)ECMAScript,描述了该语言的语法和基本对象
(2)文档对象模型(DOM),描述处理网页内容的方法和接口
(3)浏览器对象模型(BOM),描述与浏览器进行交互的方法和接口。

1.2 javascript的特点

(1)解释型语言,nodejs为其解释器
(2)弱类型语言,变量的数据类型取决于值的数据类型
    a.变量的数据类型在初始化的时候确定
    b.变量得数据类型可以随时发生变化
    c.类型细分不明显
(3)按顺序解释执行,即从上到下执行
(4)既可以作为前端脚本语言,也可以作为后端语言,取决于应用平台和使用的框架

1.3 在body和head中使用JavaScript的区别

(1)在body部分中的JavaScript会在页面加载的时候被执行,在head部分中的JavaScript会在被调用的时候才执行。
(2)浏览器解析Html是从上到下解析的。把JavaScript放在head里时,则先会被解析,但因为这时body还没有解析,所以会返回空值。一般都会绑定一个监听,当全部的html文档解析完之后再执行代码。

1.4 JavaScript数据类型

(1)5个基本数据类型(值类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol(es6中新增,表示独一无二的值)
(2)引用数据类型:对象(Object)、数组(Array)、函数(Dunction)

1.5 Undefined与Null关系

(1)undefined继承null,所以undefined==null结果为true,但是null表示空对象,undefined表示未定义
(2)null与undefined用途不同,null可以用来表示一个空对象,但是没有必要把一个变量的值显式设置为undefined。
(3)undefined===null为false,因为类型不同。

1.6 实现深拷贝的方法

(1)通过json对象实现深拷贝(JSON.stringify,JSON.parse)
(2)Object.assign()拷贝
(3)lodash函数库实现深拷贝
(4)递归的方式实现深拷贝

2 操作符及类型转换

2.1 操作符

2.1.1 算数运算符(5种)

(1) + 加法
(2) - 减法
(3) * 乘法
(4) / 除法
(5) % 取余

2.1.2 一元运算符(8种常用)

(1) + 将操作数转换成数字,字符串的拼接
(2) - 将操作数转换成数字,同时变为负数
(3) !逻辑取反运算
(4) ++ 递增
(5) -- 递减
(6) delete 删除数组或对象中特定索引的值
(7) typeof 返回当前操作数的类型
(8) void void运算符对任何值返回undefined

2.1.3 赋值运算符(6种)

(1) =
(2) +=
(3) -=
(4) *=
(5) /=
(6) %=

2.1.4 比较运算符(8种)

(1) == 等于
(2) === 值相等并且类型相等
(3) != 不相等
(4) !== 值不相等或类型不相等
(5) > 大于
(6) < 小于
(7) >= 大于或等于
(8) <= 小于或等于

2.1.5 逻辑运算符

(1) && and(同真才真,有假则假)
(2) || or(有真才真,有假则假)
(3) ! not

2.2 JavaScript隐式转换

2.2.1 原始类型转换

(1)加减乘除:1.字符串加数字,数字就会转成字符串。数字加数字或字符串加字符串不需要转换。
  在加法的过程中,首先把等号左右两边进行了求原值ToPrimitive()操作,然后如果有两个或多个原始值只要有一个是String类型,就把两个或多个原始值都进行转化字符串toString()操作,进行字符串拼接;否则把两个或多个原始值都进行转化数字toNumber()操作,进行数字相加。
(2)数字减字符串,字符串转成数字。如果字符串不是纯数字就会转成NaN。字符串减数字也一样。两个字符串相减也先转成数字。
(3)乘,除,大于,小于跟减的转换也是一样。
(4)有关==的隐式转换
    a.undefined等于null
    b.字符串和数字比较时,字符串转数字
    c.数字和布尔比较时,布尔转数字
    d.字符串和布尔比较时,两者转数字

2.2.2 引用类型的转换

(1)如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。
    a.如果输入的值已经是一个原始值,则直接返回它
    b.否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
    c.否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
    d.否则,抛出TypeError异常。
(2)如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值
    a.如果输入的值已经是一个原始值,则直接返回它
    b.否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
    c.否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
    d.否则,抛出TypeError异常。
注意:PreferredType的值会按照这样的规则来自动设置:
       a.该对象为Date类型,则PreferredType被设置为String
       b.否则,PreferredType被设置为Number

2.2.3 冒泡排序

// 冒泡排序
//1、比较相邻的两个元素,如果前一个比后一个大,则交换位置。
//2、比较完第一轮的时候,最后一个元素是最大的元素。
//3、这时候最后一个元素是最大的,所以最后一个元素就不需要参与比较大小。
function bubbleSort(arr) {
  var len = arr.length;
  //外层控制循环多少趟
  for (var i = 0; i < len-1; i++) {
    //内层控制每一趟的循环次数
    for (var j = 0; j < len - 1 - i; j++) {
         // 相邻元素两两对比,元素交换,大的元素交换到后面
        if (arr[j] > arr[j + 1]) {
            var temp = arr[j];
            arr[j] = arr[j+1];
            arr[j+1] = temp;
        }
    }
  }
  return arr;
}
//举个数组
var arr = [20,18,27,19,35];
//使用函数
bubbleSort(arr)

2.2.4 break和continue的区别

(1) 当执行brea后,会立即跳出循环体
(2) 当执行continue时,不会跳出循环,而是立即结束当前循环,进入下一次循环。

3.函数

3.1 函数的作用

(1)功能的封装
(2)直接调用
(3)代码复用率提高

3.2 函数声明

(1)函数声明
    function 函数名(形参列表){
        //函数体
    }
(2)函数表达式
      var 函数名 = function(形参列表){
            //函数体
       }
    这种形式看起来像常规的变量赋值,先创建一个匿名函数,然后赋值给变量函数名。我们知道在JS中如果要想使用一个变量,必须先给这个变量赋值,所以函数表达式也不例外,在调用之前,必须先给它赋值。否则会报错。

3.3 函数内部属性

(1)arguments
    a.函数的参数在函数内部是使用一个类数组对象来表示的。这个类数组对象就是arguments。
    b.arguments是一个类数组对象,包含着传入函数中的所有参数。arguments主要用途是保存函数参数,但是这个对象还有一个名为callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数
    c.arguments保存真正的实参
(2)this    面向对象语言中 this 表示当前对象的一个引用。
    a.在方法中,this 表示该方法所属的对象。
    b.如果单独使用,this 表示全局对象。
    c.在函数中,this 表示全局对象。
    d.在事件中,this 表示接收事件的元素。
    e.在显式函数绑定时,我们可以自己决定this的指向

3.4 IIFE 自执行函数

(1)IIFE :意为立即调用的函数表达式,也就是说,声明函数的同时立即调用这个函数
(2)作用
    a.页面加载完成后只执行一次的设置函数。
    b.将设置函数中的变量包裹在局部作用域中,不会泄露成全局变量。
(3)函数的声明和IIFE的区别
    在函数的声明中,我们首先看到的是function关键字,而IIFE我们首先看到的是左边的(。也就是说,使用一对()将函数的声明括起来,使得JS编译器不再认为这是一个函数声明,而是一个IIFE,即需要立刻执行声明的函数。两者达到的目的是相同的,都是声明了一个函数并且随后调用函数foo。
(4)IIFE的写法
    a.对返回结果不进行处理
        (function(形参){
            函数体内容
        })(实参);
    b.对返回结果不进行处理
        (function(形参){
            函数体内容
        }(实参));
    c.返回的是一个布尔值,然后进行取反
        !function(形参){
            函数体内容
        }(实参)
    d.对于数字返回的是原来的结果,非数字返回NaN
        +function(形参){
            函数体内容
        }(实参)
    e.对于数字返回的是正负符号相反,非数字返回NaN
        -function(形参){
            函数体内容
        }(实参)
    f.对于数字返回的是正负符号相反再减1,非数字返回-1
        ~function(形参){
            函数体内容
        }(实参)
    g.返回的结果是undefined
        void function(形参){
            函数体内容
        }(实参)
(5)案列-经典面试题-IIFE
    for (var i = 0; i < 6; i++) {
        function output() {
          console.log(i); // 为什么输出的是6,而不是0,1,2,3,4,5
          // 因为输出的 i 是全局作用域的,当循环结束后 i 的值是 6,所以输出的 i 就是6。
        }
      }
      output()
      for (var i = 0; i < 6; i++) {
        (function (j) {
          console.log(j); //0,1,2,3,4,5
        })(i)
        // 因为 JS 中调用函数传递参数都是值传递 ,所以当立即执行函数执行时,首先会把参数 i 的值复制一份,然后再创建函数作用域来执行函数,循环5次就会创建5个作用域,所以每个输出访问的都是不同作用域的 i 的值 。
      }
(6)为什么需要IIFE?
    IIFE的出现是为了弥补JS(ES5)在作用域方面的缺陷:JS只有全局作用域(global scope)、函数作用域(function scope),从ES6开始才有块级作用域(block scope)
(7)回调函数的作用
    回调函数一般都用在耗时操作上面:因为主函数不用等待回调函数执行完,可以接着执行自己的代码。比如ajax请求,比如处理文件等。
(8)什么是闭包? 
    闭包就是指有权访问另一个函数作用域中的变量的函数
(9)闭包的生成有三个必要条件
    a.函数嵌套函数
    b.内部函数引用了外部函数中的数据(属性、函数)
    c.参数和变量不会被回收
(10)闭包的用途
    a.可以读取函数内部的变量
    b.让这些变量的值始终保持在内存中。
(11)使用闭包的缺点
    a.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题
    b.闭包会在父函数外部,改变父函数内部变量的值,当父级的变量对象被修改时,所有子函数都受到影响

4. 数组

4.1 数组的特性

(1)每一项都可以保存任何类型的数据。
(2)数组的大小是可以动态调整。
(3)数组的length属性:可读可写,可以通过设置length的值从数组的末尾移除项或向数组中添加新项

4.2 数组的创建

(1)字面量创建数组
    由一对包括元素的方括号"[]"表示,元素之间以逗号","隔开
    var arr = [12,name,true,"larry",{},function(){},[],null];
(2)通过Array构造函数来创建数组
    var names = new Array(); 
    var names = new Array('terry','robin')

4.3 数组访问

访问数组元素 数组变量名[索引]
通过索引访问数组,数组的索引从0开始,数组的索引超过数组长度会访问到undefined值而不会报错。数组的长度通过length属性获取
  a) [index]  直接访问,索引可以超过索引范围,只不过访问的值为undefined
  b) length-1=Max(index)
  c) length+N 或 length-N 开辟新的内存空间 或 数组元素的删除

4.4 数组API

4.4.1 数组序列化

(1) toString() 在默认情况下都会以逗号分隔字符串的形式返回数组项
      var arr = [1,5,2,8,10,{a:1}];
      console.log(arr.toString());//”1,5,2,8,10,[object Object]”
(2)join() 使用指定的字符串用来分隔数组字符串
    var arr = [1,5,2,8,10,{a:1}];
    console.log(arr.join("-"));//”1-5-2-8-10-[object Object]”

4.4.2 构造函数的方法

(1) Array.isArray() 用来判断某个变量是否是一个数组对象
(2) Array.from() 从类数组对象或者可迭代对象中创建一个新的数组实例。
(3) Array.of() 根据一组参数来创建新的数组实例,支持任意的参数数量和类型。

4.4.3 栈与队列方法

(1) Array.prototype.push()   push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度。
(2) Array.prototype.pop()    pop() 方法用于删除数组的最后一个元素并返回删除的元素。
(3) Array.prototype.shift()  shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。
(4) Array.prototype.unshift()  unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。

4.4.4 排序方法

(1) Array.prototype.reverse()  reverse() 方法用于颠倒数组中元素的顺序。
(2) Array.prototype.sort()  sort() 方法用于对数组的元素进行排序 如果调用该方法时没有使用参数,将按字母顺序(Ascall编码)

4.4.5 操作方法

(1) Array.prototype.concat()  concat() 方法用于连接两个或多个数组
(2) Array.prototype.slice()  slice()方法可提取字符串的某个部分,并以新的字符串返回被提取的部分
(3) Array.prototype.splice()  splice() 方法用于添加或删除数组中的元素。

4.4.6 位置方法

(1) Array.prototype.indexOf() indexOf() 方法可返回数组中某个指定的元素位置。
(2) Array.prototype.lastIndexOf()  lastIndexOf() 方法可返回一个指定的元素在数组中最后出现的位置,从该字符串的后面向前查找。

4.4.7 迭代方法

(1) Array.prototype.every()
      every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
      every() 方法使用指定函数检测数组中的所有元素:
      - 如果数组中检测到有一个元素不满足,则整个表达式返回 false,且剩余的元素不会再进行检测。 
      - 如果所有元素都满足条件,则返回 true。
 (2) Array.prototype.some()
      some() 方法用于检测数组中的元素是否满足指定条件(函数提供)。
      some() 方法会依次执行数组的每个元素:
      - 如果有一个元素满足条件,则表达式返回*true* , 剩余的元素不会再执行检测。
      - 如果没有满足条件的元素,则返回false。
  (3) Array.prototype.filter()
        filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
  (4)Array.prototype.map()
      map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
  (5) Array.prototype.forEach()
        forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。

你可能感兴趣的