JavaScript基础知识笔记

一、JavaScript的数据类型相关

基本数据类型:
  1. number (NaN是一种特殊值,它不等于任何值,包括它自己,属于number类型)
  2. string
  3. boolean
  4. null
  5. undefined
  6. Symbol
  7. Object (包括狭义上的对象、函数、数组)

注意点:
对象的键名为字符串,若命名为数值,则会自动转为字符串;如果键名不符合标识名的条件,则必须加上引号。
数值键名在用于对象的属性获取时,只能使用 [ ] 方式获取,不能使用 . 运算符获取


数据类型检测相关
  1. typeof
	//基本数据类型
	typeof(Number) ======> 'number'
	typeof(String) ======> 'string'
	typeof(Boolean) ======> 'boolean'
	//特殊数据类型
	typeof(null) ======> 'object'
	typeof(undefined) ======> 'undefined'
	//合成数据类型
	typeof(函数) ======> 'function'
	typeof(狭义上的对象) ======> 'object'
	typeof(数组) ======> 'object'
	//因此区分数组与对象数据时,一般采用 instanceof 方法
  1. instanceof 运算符
    用来验证一个对象是否为指定的构造函数的实例。
  2. toString
    Object 的实例方法 toString() 会返回对象的类型字符串,因此可以用来判断一个值的类型。另外由于实例对象的可以自定义实例方法,所以使用时最好是 Object.prototype.toString 方法配合函数的 call 方法在任意值上调用这个方法,帮助判断这个值的类型。
    	Object.prototype.toString.call(2)				// "[object Number]"
    	Object.prototype.toString.call('')				// "[object String]"
    	Object.prototype.toString.call(true)			// "[object Boolean]"
    	Object.prototype.toString.call(undefined)		// "[object Undefined]"
    	Object.prototype.toString.call(null)			// "[object Null]"
    	Object.prototype.toString.call(Math)			// "[object Math]"
    	Object.prototype.toString.call({})				// "[object Object]"
    	Object.prototype.toString.call([])				// "[object Array]"
    
  3. isNaN
    • 用来判断值是否为 NaN。
    • 只对数值有效。若参数为其他类型,会先转换为数值,因此当 isNaN 为 true 时,不一定表示值为 NaN,也可能是字符串、对象、部分数组。

数据类型转换相关方法
  1. parseInt()(用于将字符串转化为整数)
    • 会将数据先转换为字符串再转换为数值,最后转为数值时是一个个字符依次转换。若第一个字符就不能转换为数字,则返回 NaN,因此转化空字符、null、undefined 时都返回为 NaN。
    • 方法含有两个参数,分别为被转换的值、被转换的值的进制。
  2. parseFloat()(用于将字符串转化为浮点数)
    • 由于 parseFloat 方法的特性使它和 Number 转换方法的结果会不同。
    • 若参数不是字符串,或字符串首位不能转化为浮点数,则返回 NaN(如空字符串)。
  3. Number()(将任意类型的值转化为数值)
    • 转换空字符传返回0,转换 null 返回0,转换 undefined 返回 NaN。
    • Number 转换字符串与 parseInt 的区别是只要有一个字符无法转换成数值,就返回 NaN。
    • Number 转换对象时先调用对象的 valueOf 方法,返回值为原始类型值后,就直接使用 Number方法;若返回值还是对象,则调用它的 toString 方法,返回值为原始类型值后,直接使用 Number 方法;若还是对象,就报错。
  4. String()(将任意类型的值转化为字符串)
    • String 方法转换对象时和 Number 类似,只不过把 toString 方法和 valueOf 方法的执行顺序互换。先调用对象的 toString 方法,返回值为原始类型值后,就直接使用 String 方法;若返回值还是对象,则调用它的 valueOf 方法,返回值为原始类型值后,直接使用String 方法;若还是对象,就报错。
  5. Boolean()(将任意类型的值转化为布尔值)
    • 其他数据类型转为布尔值时,undefined、null、false、0、NaN、空字符串6中数据为false;其余数据皆为true,包括空数组[ ]与空对象{ }

比较运算符:
  1. 非相等运算符:
    比较字符串时按照字典顺序比较;
    比较非字符串原始数据类型时先转换为数值再比较,NaN与任何值比较都返回 false
    比较非字符串对象时会转换为原始类型的值再比较,对象转换为原始对象时的算法是先调用 valueOf 方法,若结果还是对象,则继续调用 toString 方法。
  2. 严格相等运算符:
    先比较数据类型;
    比较复合类型数据时,比较的是它们是否指向同一个地址。
  3. 在相等运算符(==)中,null 与 undefined 相等

循环遍历方法对比:

性能上: for > forEach > map,但是考虑到代码的语义化,因此不是特别强调性能的情况下,根据不同情况使用不同方法。
for : 基本循环语法
forEach : 数组的遍历方法,不返回值,无法中断执行
map: 数组的遍历方法,将每次的执行结果组成一个新数组返回
for … in … : 遍历对象的属性,包括对象所继承的属性
Object.keys() : 遍历对象的属性,返回一个对象自身属性名组成的数组,只返回可枚举属性
Object.getOwnPropertyNames() : 遍历对象的属性,返回一个对象自身属性名组成的数组,包括不可枚举的属性名

二、错误处理语法

  1. throw 语句

    手动终端程序执行,抛出一个错误,参数可以是任意值

    	throw 123;
    	//Uncaught 123
    
  2. try … catch … finally

    捕获抛出的错误并进行处理,try 代码块里抛出错误, catch 代码块进行捕获处理,finally 代码块表示是否出现错误,最后都要运行的语句,finally 代码块可以省略。
    当 try 代码块或 catch 代码块中存在 return 语句时,会先执行 finally 代码块再进行 return。

    	function test(){
    		try {
    			console.log(0);
    			throw 'bug';
    		} catch(e) {
    			console.log(1);
    			return true;
    			console.log(2);
    		} finally {
    			console.log(3);
    			return false;
    			console.log(4);
    		}
    		console.log(5);
    	}
    	let result = test();
    	console.log(result);
    	//结果依次为:
    	//0
    	//1
    	//3
    	//false
    

三、对象

Object 本身可以作为工具函数使用,也可以作为构造函数使用

  • Object() 作为工具方法使用时,会将任意值转为对象。
    若参数为空/ undefined / null 则返回一个空对象;
    若参数为原始类型的值,Object 会将其转为相应的包装对象的实例;
    若参数是一个对象,则返回该对象,不做转换。
    因此可以通过这一点,可以写一个判断对象是否为对象的函数。
function isObject( value ){
	return value === Object(value);
}

Object 作为构造函数使用时,和工具函数类似。当参数为对象时,直接返回该对象;参数为原始类型的值时,返回其相应的包装对象。他们的区别是语义不同,工具函数是将一个值转为对象,而构造函数表示是新生成一个对象。


Object 对象的原生方法:

  1. Object 对象本身的方法
  2. Object 对象的实例方法,即定义在 Object 原型对象 Object.prototype 上的方法

实例方法 hasOwnProperty()

即 Object.prototype.hasOwnProperty() 接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否有该属性。


包装对象

当与数值、字符串、布尔值相对应的 Number、String、Boolean, 作为构造函数使用时,他们会把原始类型的值转为对象。

let test = 'abc';
typeof String(test);		//string
typeof new String(test);	//object

在有些情况下原始类型的值也会自动当作包装对象使用,并在使用后立即销毁。原始类型值的相关方法和属性就相当于使用时自动当作包装对象使用。

//此时'a'是一个字符串,但是它可以使用对象的属性
'a'.length;

对象相关方法注意
  1. 属性是否存在的 in 运算符 和属性的遍历 for…in 循环都会包括对象所继承的属性,如果只需要返回该对象自身的属性还需通过 hasOwnProperty 方法做进一步判断。

四、Array对象

Array构造函数

由于 Array 作为构造函数时,不同的参数会有不同的行为,因此不建议使用它来生成新数组。


实例方法:

slice() 方法

提取目标数组的一部分,返回一个新数组,不改变原数组。

splice() 方法

删除原数组的部分成员,并可以在删除位置添加新成员,返回被删除的元素,会改变原数组。

sort() 方法

对数组成员进行排序,改变原数组。默认是按照字典顺序排,不是大小。
自定义排序时,sort() 传一个函数作为参数,函数的参数为进行比较的两个数组成员,若函数返回值大于0,表示第一个成员排在第二个后面;其余情况都是第二个排在后面。

join() 方法

指定参数作为分隔符,将所有成员连接为一个字符串返回,默认使用逗号。


数组的空位相关:

  1. 数组的空位获取时,返回 undefined;
  2. 数组使用 delete 方法时会形成空位,且不影响 length 属性;
  3. 数组的某个位置是空位和某个位置是 undefined 是不同的,使用 for … in 、forEach 、Object.keys 来遍历数组时会跳过空位,但是不会跳过值为 undefined 的位置;

类数组对象:

具有 length 属性的对象,即可认为该对象是类数组对象

类数组对象转换为数组可以使用数组的 slice 方法:

Array.prototype.slice.call(类数组对象)

如果类数组对象想要使用数组的方法,可以通过 call() 把数组的方法放到类数组对象上,但是这种方式使用数组某些方法时性能会降低,所以推荐先将类数组对象转化为数组,在使用数组的方法

//类数组对象使用数组的 forEach 方法
Array.prototype.forEach.call(类数组对象,function(item,index){
	console.log(`${index}:${item}`);
});

五、String包装对象

实例方法:

slice() 方法

提取目标字符串的一部分,返回一个新字符串,不改变原字符串。两个参数分别为开始位置和结束位置(不包含该位置)。

substring() 方法

提取目标字符串的一部分,返回一个新字符串,不改变原字符串。与slice() 作用类似,不过由于它对不合理参数的自动转换违反直觉,所以不建议使用。

substr() 方法

提取目标字符串的一部分,返回一个新字符串,不改变原字符串。与slice() 作用类似,不过两个参数分别为开始位置和截取长度。第二个参数为负数自动转为0。

trim() 方法

去除字符串两端空格,返回新字符串,不改变原字符串。

match() 方法

确定原字符串是否匹配某个子字符串,返回一个数组,成员为匹配的字符串,没有匹配到则返回 null。
返回的数组含有 index 和 input 属性,分别表示匹配字符串开始的位置,原字符串。

search() 方法

用法基本等同于 match(),不过返回的是匹配的第一个位置,没有匹配则返回-1。

replace() 方法

用于替换匹配的子字符串,一般情况下只替换第一个匹配子字符串,若是使用含 g 修饰符正则表达式则替换全部匹配的子字符串。

split() 方法

按照规格分割字符串,返回由子字符串组成的数组。
可以使用第二个参数,限定返沪数组的最大成员数量。


六、RegExp对象

实例属性:

RegExp.prototype.ignoreCase

返回一个布尔值,表示是否设置了 i 修饰符。

RegExp.prototype.global

返回一个布尔值,表示是否设置了 g 修饰符。

RegExp.prototype.multiline

返回一个布尔值,表示是否设置了 m 修饰符。

RegExp.prototype.flags

返回一个字符串,包含已经设置的所有修饰符。

RegExp.prototype.lastIndex

返回一个整数,表示下一次搜索开始的位置,该属性可读写,只有在连续搜索时有意义。

RegExp.prototype.source

返回正则表达式的字符串形式,属性只读。


实例方法:

test() 方法

返回一个布尔值,表示当前模式是否能够匹配参数字符串。
注意:当正则表达式带有 g 修饰符时,test() 会从上一次结束的位置开始向后匹配,正则表达式内容会记录上一次的 lastIndex 属性,此时不应该更换所要匹配的字符串,结果会不准确。

exec() 方法

返回匹配结果。若发现匹配,返回一个数组,成员是匹配成功的子字符串,否则返回 null 。
注意: 若正则表达式带有 g 修饰符时,多次执行,下次搜索的位置从上一次匹配成功结束的位置开始。

七、JavaScript执行过程

执行的三步骤:

  1. 语法分析
  2. 预编译
  3. 解释执行

语法分析是先通篇扫描找出语法错误,不执行;之后进行预编译,最后解释执行。
其中预编译的主要流程大概是:

  1. 创建AO对象,并找出形参和变量的声明作为AO对象的属性名,值都为undefined;
  2. 将实参和形参对应,修改AO相应属性的值为实参;
  3. 将函数声明与AO属性对应,修改AO相应属性的值为函数声明;

然后在AO对象的基础上解释一行执行一行,就解释执行。
详细过程参考

八、原型链

所有对象都有自己的原型对象,因为原型对象也是对象,所以原型对象也有自己的原型对象,就形成了原型链。
如果向上找,所有对象的原型都会指向 Object.prototye,即 Object构造函数的 prototype属性,而Object.prototye的原型是 null, 因此原型链的尽头是 null

九、绑定this指向的callapplybind方法

call、apply的作用都是改变 this 指向,然后调用该函数。
call 的第一个参数当为空、null、undefined 时,this 指向全局对象,多余的参数表示函数的入参。
apply 的第一个参数为 null、undefined 时,this 指向全局对象,第二个参数则为数组,表示函数的入参。

function test (a, b){
	console.log(a+b);
}
test.call(null,1,2);
test.apply(null,[1,2]);

bind 方法将函数体内的 this 绑定在某个对象上,并返回一个新函数。若第一个参数为 null、undefined 时等于将 this 绑定在全局对象上。
注意:根据 bind方法的特性 bind()方法每运行一次返回的就是一个新函数。

九、对象的深拷贝

对象的深拷贝主要需要实现:

  1. 拷贝后的对象与原对象有相同的原型;
  2. 拷贝后的对象有原对象的实例属性。

Object.create()的第一个参数是要继承的原型,第二个参数是属性描述对象,用来添加新属性到创建的对象上。

//使用ES2017写法
function copyObj(orig){
	return Object.create(Object.getPrototypeOf(orig),Object.getOwnPropertyDescriptors(orig));
}
//其他写法
function copyObj(orig){
	let copy = Object.create(Object.getPrototypeOf(orig));
	copyOwnPropertiesFrom(copy, orig);
	return copy;
}
function copyOwnPropertiesFrom(target, source) {
  Object.getOwnPropertyNames(source).forEach(function (propKey) {
      let desc = Object.getOwnPropertyDescriptor(source, propKey);
      Object.defineProperty(target, propKey, desc);
    });
  return target;
}

你可能感兴趣的:(JavaScript基础知识笔记)