概览
在前面的内容中我们主要讲解了变量,内存,作用域,数组,时间对象,函数,闭包,包装对象,内置对象,类和面向对象,继承这么几个东西,接下来一起来总结一下。
变量
变量的创建
需要使用var关键字,如果你不使用var关键字的时候创建的是全局变量,变量的创建仅仅是起了一个名字而且因为预处理机制的存在会发生声明提前的问题。
一个完整的创建变量的过程分为3个步骤,1创建名字 2确定作用范围 3将创建的过程提升到所在函数的最顶端
变量的赋值
对于基础数据类型而言是直接保存到变量当中,而对象而言是保存到内存当中,然后把内存的地址保存到变量当中。
变量的操作
增删属性操作:
对于基础数据类型而言,不会报错,也没有效果。
对象正常
修改:
相当于重新赋值
复制:
基础数据类型复制出来的变量和原先的变量相互独立,没有关系。
引用数据类型复制的仅仅是内存的地址,相当于多了一个别名,相关的操作会有影响。
作为函数参数的变量,如果是基础数据类型,相当于赋值了一份作为函数的局部变量,和原先的变量相互独立,互不影响。
如果是引用数据类型。
那么参数传递的是一个内存的地址,这时会发生两种情况1对参数进行修改,原先的对象也会有相应的变化2对参数进行赋值,这个时候相当于在函数内部重新创建了一个变量,并且断开和原先变量的联系,所以不会对原先的变量有任何的作用。
作用域
什么是作用域
声明函数如何处理
同时声明函数和变量时如何处理
作用域的欺骗
作用域链
垃圾回收机制
手动内存管理机制
数组
数组的创建
两种方式new 和[ ]
注意使用new的时候可以传入一个数字来表示数组的长度,但是这样的数组是不能使用forEach等循环的,如果需要循环可以使用Array.apply(null,{length:5})来实现
数组的检测
Object.prototype.toString.call(value)===‘[object array]’
数组的方法
ES3
push pop shift unshift reverse sort对原数组有影响
concat slice splice indexOf lastIndexOf 对原数组无影响
ES5
every filter forEach map some reduce reduceRight
重点要注意的方法:
sort 默认是按照asc码进行排序,可以接受排序函数,函数的返回值需要是数字,sort方法会根据结果是否大于0来决定排序顺序
splice 数组最强大的方法,可以对数组进行任何操作,一个参数时用于截取,两个参数时用于删除,三个或更多参数时用于修改。
返回一个新数组,对原数组没有影响。
伪数组的处理
Array.prototype.slice.call(value)
数组的去重
面试中经常被问到的问题,重点掌握,一共整理了6中方法。
相关的代码和思路会同步更新到知乎专栏中。
时间对象
时间对象的起点是1970年1月1日0点。
创建时间对象
只有一种方式new Date()不传参的时候取系统本地时间,如果参数为数字,这个数字表示一个毫秒数,将创建一个1970年1月1日0点+毫秒数所对应的时间。
如果传入一个字符串,那么将创建一个该字符串所表示的时间。
虽然时间对象对字符串的处理能力及其强大,但是推荐使用“月/日/年 时:分:秒”的方式进行进行创建。
如果传入的参数无法解析成时间,将返回一个特殊的对象,叫做Invalid Date。
时间对象的方法
时间对象有非常多的方法,死记硬背并不容易,所以在使用这些方法的时候需要使用一些技巧,就是将方法拆分为三部分,[get|set][UTC][time],time部分可以总结为,年月日时分秒和毫秒,一共28个方法
注意:
年需要使用fullyear,日期需要使用date,而不是day,day表示的是星期,他只有get方法没有set方法。
如果想输出日期,可以使用格式化方法(toUTCString等),但是要注意在不同的浏览器产生的结果是不同的,所以一般不使用,只有在按照一个格式输出,并且按照这个格式读取的时候会用到,也就是cookies过期时间的设置。
时间对象的转化
在很多时候需要将时间对象转换为毫秒数,我们介绍了5种方法完成这个操作,他们的性能存在一定的差距,但是并不大,你可以按照自己的习惯来书写,如果希望代码简单,可以使用一元加操作符,如果希望可读性好一点可是使用valueof方法,唯一不建议使用的就是parse方法,因为性能比较低。
函数
六种创建函数的方式
1.使用声明语句声明一个有名字的函数,提升整个函数,有name属性
2.使用声明语句声明一个匿名函数并赋值给一个变量,仅提升变量,没有name属性
这两种方式创建的函数注意有两个区别,但都不影响使用,使用哪种都可以。
通常我们建议使用函数声明的方式去写,并且写到整个函数的最顶端,但是有一种情况需要使用变量的方式,就是在语句中去创建不同的函数。
3.使用声明语句去创建一个有名字的函数,然后把它赋值给一个变量。
使用这种方法一般用于借助name属性进行递归调用
4.箭头函数:
ES6的写法,只能创建匿名函数,并且内部没有this,没有arguments
5.函数生成器:
ES6写法,了解即可
6.函数构造器:
不建议使用,让你用你都不会用。
IIFE
自执行函数,主要原理是让函数声明语句变成函数表达式,常用括号包裹。
也可以使用其他的结构,比如new !
~等等
作用
1.避免全区作用域的污染
2.提升性能,减少作用域的查找
3.便于代码压缩
4.避免或者说解决命名冲突(jQuery的案例)
5.保存闭包状态,在for循环中使用,考试常考。
6.改变代码运行顺序,即AMD CMD UMD各种模块化模式
理解IIFE最重要的就是理解函数作用域,建议重新听一下函数作用域这张的内容
闭包
什么是闭包
当函数的返回值为函数的时候产生的一种特殊的现象。
闭包的产生
函数的执行可以分为几个过程,创建活动对象,声明变量和函数添加到活动对象上,执行代码,垃圾回收。
正常情况下函数执行完成之后,活动对象会被垃圾回收机制清理掉,但是如果函数的返回值是函数,那么因为内部活动对象和外部活动对象产生了引用关系,所以不会被垃圾回收机制回收。
所以活动对象上的变量被保存了下来。
闭包的产生不太好理解所以我们在教程中用酒店,任意门,保洁阿姨的案例来解释了这件事情。
闭包的作用
保存变量
闭包的问题
占用内存
闭包的清理
将返回的函数对应的变量设置为null。
包装对象
基础数据类型在调用方法或属性的时候产生的临时的对象
5种基础数据类型中只有Number,String,Boolean有包装对象,Null和undefined没有,所以调用Null和undefined的方法或属性的时候会报错。
包装对象对应的方法
布尔类型没有方法
数字类型中的常用方法toFixed,保留小数点后N位
字符串类型提供了14个方法,这些方法只要你知道了他们的用途,基本上不会用错,但是有三个方法是最常用,也最容易用错的:
slice,substring,substr。
他们的功能相同,都用于字符串的截取,参数也一样,都是一个或两个数字。
区别在于如果参数为负数,那么slice可以从开始位置截取到倒数第几位,而substring,substr会把这个负数转换为0来处理。
substring,substr想比较,一个是从开始位置截取到结束位置,一个是从开始位置截取N个。
如果参数都是正数,在大部分情况下,对于slice,substring而言,第二个参数减第一参数就是截取后的长度,对于substr而言第二个参数就是截取后的长度。
内置对象
什么是内置对象,JS解释器中已经定义好的对象,使用的时候不需要NEW
JS有哪些内置对象,global,math,json
global方法分三类
1处理数字的,一共4个isFinite isNaN parseInt parseFloat
2处理URI的也是4个[encode|decode]URI[Component]
[encode|decode]:
编码和反编码
[Component]:
是否对所有特殊字符进行编码
3eval:
接受一个字符串作为参数,作用就是将这个字符串作为语句执行
作用
1.在低版本的浏览器下将字符串形式的JSON结构转换成对象
2.动态声明局部变量
3.代码压缩
提取码f6td