JavaScript 学习笔记 && 面试题

2020-10-13

常用浏览器

  • webkit内核(V8引擎)
    • 谷歌 Chrome
    • Safari
    • Opera >= V14
    • 国产浏览器
    • 手机浏览器
  • Gecko
    • 火狐firefox
  • Presto
    • Opera < V14
  • Trident
    • IE
    • IE Edge 开始采用双内核(包含chrome mini)
      在这里插入图片描述

JS做客户端语言

按照相关的js语法,去操作页面中的元素,有时还需要操作浏览器里面的一些功能

  • ECMAScript3/5/6…:JS的语法规范(变量、数据类型、操作语句等等)
  • DOM(document object model)文档对象模型,提供一些JS的属性和方法,用来操作页面中的DOM元素
  • BOM(broswer object model)浏览器对象模型,提供一些JS的属性和方法,用来操作浏览器

JS中的变量 variable

变量: 可变的量,在编程语言中,变量其实就是一个名字,用来存储和代表不同值的东西。

	// 创建变量的几种方式
	// ES3
	var a = 12;
	console.log(a); //=>输出的是a代表的值12
	
	// ES6
	let b = 100;
	b = 200;
	
	//常量
	const c = 1000;
	c = 2000; //=>报错,常量的值不能被修改

	// 创建函数也相当于创建变量
	function fn(){}

	//创建类也相当于创建变量
	class A{}

	//ES6的模块导入也相当于创建变量
	import B from 'b.js';

	//Symbol 创建唯一值
	Symbol c = 100;

JS中的命名规范

  • 严格区分大小写
  • 使用数字、字母、下划线$,不能以数字开头
  • 使用驼峰命名法:首字母小写,其余每一个有意义单词的首字母大写(命名尽可能语义化明显,使用英文单词)
  • 不能使用关键字和保留字(当下有特殊含义的是关键字,未来可能成为关键字的叫保留字)

JS中常用的数据类型

  • 基本数据类型
    • 数字 number (常规数字和NaN)
    • 字符串 string 所有单引号、双引号和反引号包起来的都是字符串
    • 布尔 boolean true/false
    • 空对象指针 null
    • 未定义 undefined
  • 引用数据类型
    • 对象数据类型 object
      • {} 普通对象
      • [] 数组对象
      • /^$/ 正则对象
      • Math 数学函数对象
      • 日期对象 Date
    • 函数数据类型 function

number 数字类型

包含:常规数字和NaN

NaN

not a number:不是一个数,但它隶属于数字类型

NaN和任何值(包括自己)都不相等: NaN != NaN, 所以不能用双等号的方式判断是否为有效数字

isNaN

检测一个值是否为非有效数字,如果不是有效数字返回true,反之返回false

在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是先基于Number()方法,把值转换为数字类型,然后再检测。

// isNaN([val])
console.log(isNaN(10)); //false
console.log(isNaN('AA')); //true
console.log(isNaN('10')); //false

把其它类型值转换为数字类型

  • Number([val])
    • 把字符串转换为数字,只要字符串中包含任意一个非有效数字字符(第一个点除外)结果都是NaN,空字符串会变为零
      console.log(Number('12.5'))// 12.5
      console.log(Number('12.5px'))// NaN
      console.log(Number('12.5.5'))// NaN
      console.log(Number(''))// 0
      
    • 布尔值转换为数字 true是1 false是0
      console.log(true); //1
      console.log(false); //0
      console.log(isNaN(false)); //false 因为false会被转换为数字
      console.log(isNaN(true)); //false 因为true会被转换为数字
      
    • null 和undefined 转换为数字类型 null -> 0 undefined -> NaN
      console.log(Number(null)); //0
      console.log(Number(undefined)); //NaN
      
    • 把引用数据类型转换为数字,是先把它基于toString方法转换为字符串,然后再转换为数字
      console.log(Number({name: '10'})); //NaN
      console.log(Number({})); //NaN
      console.log(Number([])); //0
      console.log(Number([10])); //10
      console.log(Number([10, 20])); //NaN
      
  • parseInt/parseFloat([val], [进制]):转换为数字的方法,对于字符串,是从左到右依次查找有效数字字符,直到遇到非有效数字后停止,不管后面是否还有有效数字都不再找了,然后把找到的当数字返回
    parseInt/parseFloat是用来处理字符串的,所以如果遇到其它类型也要先转换为字符串然后再转数字
    let str = '12.5px';
    console.log(Number(str)); //NaN
    console.log(parseInt(str)); //12
    console.log(parseFloat(str)); //12.5
    console.log(parseFloat('width:12.5px')); //NaN
    
  • == 进行比较时可能出现要把其它类型值转换为数字

string字符串数据类型

所有用单引号、双引号、反引号(ES6模板字符串)包起来的都是字符串

把其它类型值转换为字符串

  • [val].toString()

    null 和 undefined是禁止直接使用toString的
    null.toString(); //会报错,但是和undefined一样转换为字符串的结果就是‘null’/‘undefined’
    普通对象.toString()的结果是’[object Object]’,原因是Object.prototype.toString方法不是转换为字符串的而是用来检测数据类型的

    let a = 12;
    console.log(a.toString()); //'12'
    console.log((NaN).toString()); //'NaN'
    console.log({name:'10'}.toString()); //'[object Object]'
    
  • 字符串拼接

    在四则运算中,除加法之外,其余都是数学运算,只有加法可能存在字符串拼接(一旦遇到字符串则不是数学运算而是字符串拼接)

    console.log('10' + 10); //'1010'
    console.log('10' - 10); //0
    console.log('10px' - 10); //NaN
    

boolean 布尔数据类型

只有两个值true/false

把其它类型转换为boolean值

只有0、NaN、‘’、null、undefined五个之转换布尔值为false,其余的都为true(没有任何特殊情况)

  • Boolean([val])
		console.log(Boolean(0));// false
		console.log(Boolean(''));// false
		console.log(Boolean(' '));// true
		console.log(Boolean(null));// false
		console.log(Boolean(undefined));// false
		console.log(Boolean([]));// true
		console.log(Boolean([12]));// true
  • !/!!
		// !:取反(先转布尔,再取反)
		console.log(!1);//false
		//!!:取反再取反,转换为布尔相当于Boolean
		console.log(!!1);//true
  • 条件判断
	//如果条件只是一个值,不是==或===或!=等这些比较,是要把这个值先转换为布尔然后验证真假
	if(1){}

null / undefined

null 和 undefined都代表没有

  • null:意料之中,一般都是开始不知道值,我们手动设置为null,后期再赋值
		let num = null;//不占用内存空间
		//....
		num = 100;
  • undefined:意料之外
		let num;//创建一个变量没有赋值,默认值是undefined

对象数据类型 - 普通对象

{[key]:[value],…}任何一个对象都是由零到多组键值对(属性名:属性值)组成的且属性名不能重复,属性名是数字或字符串格式。

删除属性
delete 对象名.属性名,把属性彻底删除
对象名.属性名 = null; 属性还在,值为空

2020-10-14

堆栈底层机制

在这里插入图片描述

JS中的数据类型检测

  • typeof [val]:用来检测数据类型的**运算符**
    • 基于typeof检测出来的结果首先是一个字符串,字符串中包含对应的类型
    • 局限性:typeof null => “object” 但是null并不是对象类型
    • 基于typeof无法细分出当前值是普通对象还是数组对象等,因为只要是对象数据类型,返回的结果都是"object"
  • instanceof:用来检测当前实例是否隶属于某个类
  • constructor:基于构造函数检测数据类型(也是基于类的方式)
  • Object.prototype.toString.call():检测数据类型最好的办法

匿名函数

匿名函数表达式:把一个匿名函数本身作为值赋值个其它东西,这种函数一般不是手动触发执行,而是靠其它程序驱动触发执行(如:触发某个事件的时候执行)

2020-10-16

浏览器的常用输出方式

  • console.log/dir/table…:控制台输出
    • console.log:在控制台输出信息
    • console.dir:输出一个对象的详细键值对信息
    • console.table:把一个多维JSON数组在控制台按照表格的方式输出
  • 浏览器弹出窗口 alert/confirm/prompt
    • 三种方式输出的结果都必先经过toString转换为字符串
    • 三种方式都会阻断JS代码执行,只有窗口关掉JS才会继续执行
  • document.write在页面中写入信息,输出结果都是字符串

2020-10-19

== VS ===

==: 相等,数据类型不同,先转换为一样的再比较
===: 绝对相等,必须类型和值都相同才返回TRUE,(switch判断中,)
每一种case的值比较都是基于“三个等号”来完成的

let a = '10';
a = a + 1 => '101'
a += 1 => '101'
a++ => 11 //a++和以上两种完全不一样,它是纯粹的数学运算

let b = '10'
switch(b){
	case 10:
		b++;
		break;
	default:
		b--;
		break;
}
console.log(b); // 9

数据类型基础知识变态练习题

!(!"Number(undefined)") //true
isNaN(parseInt(new Date())) + Number([1]) + typeof undefined;//'2undifined'
Boolean(Number("")) + !isNaN(Number(null)) + Boolean("parseInt([])") + typeof !(null);// '2boolean'
parseFloat("1.6px") + parseInt("1.2px") + typeof parseInt(null); //'2.6number'
isNaN(Number(!!Number(parseInt("0.8")))); //false
console.log(1 + "2" + "2");//'122'
!typeof parseFloat('0');// false
Number("");//0
typeof "parseInt(null)" + 12 + !!Number(NaN); // 'string12false'
!typeof (isNaN("")) + parseInt(NaN); //NaN
typeof !parseInt(null) + !isNaN(null);//'booleantrue'

2020-10-20

函数执行的底层原理

创建函数开辟的堆内存中存储的是函数体中的代码,但是是按照字符串存储的
每一次函数执行的目的都是把函数体中的代码(先从字符串变为代码)执行
每次执行都会形成一个全新的私有栈内存
在这里插入图片描述

arguments函数内置的实参集合

  1. 类数组集合,集合中存储着函数执行时传递的所有实参信息
  2. 不论是否设置形参,arguments都存在
  3. 不论是否传递实参,arguments也都存在
  4. arguments.callee:存储的是当前函数本身(一般不用,JS严格模式下禁止使用这些属性)
//arguments 任意数求和案例
function sum(){
	let total = null;
	for(let i = 0; i < arguments.length; i++){
		let item = Number(arguments[i]);
		if(isNaN(item)){
			continue;
		}
		total += item;
	}
	return total;
}

let result = sum(10, 20, 30, 40);
console.log(result); //100
result = sum(19,20);//39
console.log(result);
result = sum(10, 'aa');//10
console.log(result);

箭头函数 arrow function

  1. 如何函数中只有一行RETURN,则可以省略RETURN和大括号,多行不可以。
  2. 如果只有一个形参则小括号可以直接省略
  3. 箭头函数中没有arguments,但可以用…变量名代替(…剩余运算符
function sum(n, m){
	return n + m;
}
//=>
let result = (n, m) => n + m;

function fn(n){
	return function(m){
		return n + m;
	}
}
//=>
let fn = n => m => n + m;

2020-10-21

Math数学函数

  • Math.abs([number value]):获取一个数的绝对值,如果传入的不是数字类型则会用Number转换为数字
  • Math.ceil/floor([number value]):向上/向下取整
  • Math.round([number value]):四舍五入(正数中.5要进,负数中.5要舍)
  • Math.max([val1],[val2],…)/min([val1],[val2],…):获取一堆数最大值和最小值
  • Math.sqrt/pow():给一个数字开平方/求一个数的多少次幂
  • Math.random():获取0~1间的随机小数
  • Math.round(Math.random()*(m-n)+n) 获取n~m间的随机整数,包含n和m

JS中数组常用方法剖析

  • 方法的作用和含义
  • 方法的实参(类型和含义)
  • 方法的返回值
  • 原来的数组是否会发生改变

1. 实现数组增删改的方法
原来数组会改变

push
push: 向数组末尾增加内容
@params:多个任意类型
@return:新增后数组的长度

let arr = [10,20];
let len = arr.push(30, 'AA', {name:'array'});
console.log(len, arr);

unshift
unshift: 向数组开始增加内容
@params:多个任意类型
@return:新增后数组的长度

shift
shift: 删除数组中的第一项
@params
@return:删除的那一项

pop
shift: 删除数组中的最后一项
@params
@return:删除的那一项
基于原生js让数组长度变小也可以删除数组后面的项

let arr = [1,2,3];
arr.length--;//删除最后一项

splice
splice: 实现数组的删除
@params:
n,m都是数字,从索引n开始删除m个元素,m不写默认删除到数组末尾,如果只传个0则清空数组
@return:把删除的部分用新数组存储来返回

//删除最后一项
arr.splice(arr.length-1);
//删除第一项
arr.splice(0,1)

splice
splice: 实现数组的增加、修改
@params:
n,m, x 从索引n开始删除m个元素,用x占用删除的部分
n,0, x 从索引n开始一个都不删除,把x放到索引n的前面
@return:把删除的部分用新数组存储来返回

//向数组末尾追加
arr.splice(arr.length, 0, 'aaa');
//向数组kais开始追加
arr.splice(0, 0, 'bbb');

2. 数组的查询和拼接
原来数组不会改变

slice
slice:实现数组的查询
@params:n,m都是数字,从索引n开始,找到索引为m的地方(不包含m这项),如果m不传则找到末尾。若n为0,m不传则可以实现数组的克隆。
@return: 把找到的内容以一个新数组形式返回

let arr = [1,2,3,4,5,6];
let res = arr.slice(1, 3);
console.log(res); // 2, 3

//关于n和m的一些特殊情况
//1. n/m为负数
arr.slice(-1);//从数组的末尾开始取1个元素
arr.slice(-1,-5);//返回空数组,因为n>m
arr.slice(-5,-1);//n和m都为负数则从数组末尾开始算索引,最后一项为-1,倒数第二项为-2,以此类推。返回[2,3,4]
arr.slice(-1,3);//n<0,m>0返回空数组
arr.slice(1,-2);//m<-1则从n开始查到数组末尾返回[2,3,4,5,6]
arr.slice(-1,1);//n<0,m>0 返回空数组
//2. n,m均为正数且n>m
arr.slice(5,3);//返回空数组
//3. n或m为小数
arr.slice(0.5,3);//小数向下取整,返回[1,2,3]
arr.slice(0.5,0.8);//向下取整,返回空数组
arr.slice(0.5,1.8);//返回[1]
//4. n或m为非有效数字
arr.slice('sd',3);//若n为非有效数字,则从索引0开始,返回[1,2,3]
arr.slice('sd','sadf');//若m为非有效数字则返回空,不管n是否是有效数字
arr.slice('3','sadf');//若m为非有效数字则返回空,不管n是否是有效数字
arr.slice(3,'sadf');//若m为非有效数字则返回空,不管n是否是有效数字
//5. n或m大于数组长度
arr.slice(3,10);//若m大于数组长度,则找到数组末尾
arr.slice(10,3);//若n大于数组长度则返回空数组

concat
concat:实现数组的拼接
@params:多个任意值
@return: 返回拼接后的新数组,原数组不变

let arr = [1,2,3];
lert arr2 = [4,5,6];
let res = arr.concat(arr2);
console.log(res);//[1,2,3,4,5,6]

3. 把数组转换为字符串
原来数组不会改变

toString
toString:把数组转换为字符串
@params
@return:转换后的字符串,原数组不变

join
join:把数组转换为字符串
@params:指定的分隔符(字符串格式),不指定默认为逗号
@return:转换后的字符串,原数组不变
arr.join(’;’);

4. 检测数组是否包含某一项
原来数组不会改变

indexOf / lastIndexOf / includes
indexOf / lastIndexOf:检测当前项在数组中第一次/最后一次出现的索引值
@params:要检索的这一项的内容
@return:返回这一项出现的位置索引值(数字),如果没有返回-1,有则返回索引值

5. 数组的排序或排列

reverse
reverse:把数组倒过来排列
@params
@return:排列后的新数组,原数组不变

sort
reverse:实现数组的排序
@params:可以没有也可以是函数
@return:返回排序后的新数组,原数组改变。
如果不传递参数,是无法处理10以上的数字按大小排序的(默认是按每一项第一个字符来排序)
可以传递一个函数作为参数

	let arr = [10,22, 5, 1, 23,40];
	arr.sort((a,b)=>{
		return a - b;//正序
		return b - a;//倒序
	});

6. 遍历数组中每一项的方法

forEach map filter find reduce some every
详见:JavaScript数据类型 - Array类型

6. 数组去重*

  • 创建一个新的空数组,然后遍历原数组把遍历的元素添加到新数组中,添加前需判断新数组中是否已经存在该元素,如果不存在则添加
  • 用两个for循环遍历原数组,用当前项跟它后面的没一项进行对比,如果相等则删除(这里需要注意:因为操作的是同一个数组,删除元素时长度会发生变化,所以会引起数组塌陷问题)
  • 创建一个空对象,循环数组,把数组的元素作为对象的键和值存入对象,存入前需判断该属性是否存在,不存在则添加,如果存在则把元素从数组中删除。
  • 基于ES6的Set去重
    基于splice删除性能不好,当前项删除,后面每一项都要向前提一位,如果内容过多会影响性能。可以用最后一项替换当前项,然后删除最后一项的方式来删除
let arr = [1,2,3,2,2,1,3,3,2,1,1,2,4];
//方式一:创建新数组
let newArr = [];
for(let i = 0; i < arr.length; i++){
	if(newArr.includes(arr[i])) continue;
	newArr.push(arr[i]);
}

//方式二:删除数组元素
for(let i = 0; i < arr.length; i++){
	for(let j = i + 1; j < arr.length; j++){
		if(arr[i] === arr[j]){
			arr.splice(j, 1);
			//删除后需要j--,避免数组塌陷
			j--;
		}
	}
}

//方式三:创建空对象
let obj = {}
for(let i = 0; i < arr.length; i++){
	let item = arr[i];
	if(!obj[item]){//属性不存在
		//arr.splice(i, 1);
		//删除后需要j--,避免数组塌陷
		//可以用最后一项替换当前项,然后删除最后一项的方式来删除,性能比splice要好
		arr[i] = arr[arr.length-1];
		arr.length--;//删除最后一项
		//i--仍然需要,因为最后一项的值替换过来也要重新判断的。
		i--;
		continue;
	}
	obj[item] = item;
}

//方式四:new Set
arr = [...new Set(arr)]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值