【JavaScript】JS知识点梳理(二)

十、数据类型的区别

  • 基本数据类型:按值操作,值存储在栈内存中;
  • 引用数据类型:按照堆内存的地址来操作,我们把对象的键值对存储在堆内存中,我们操作的是堆内存的引用地址;
let a={},b=Symbol('1'),c=Symbol('1');
a[b]='哈哈';
a[c]='呵呵';
console.log(a[b]);//='哈哈'
/:唯一值相同不会替换。

十一、js中创建变量的六种方式

var\function\let\const\class\import

十二、数据类型面试题

1、
在这里插入图片描述
2、考察parseInt原理

var str = 'abc123';
var num = parseInt(str);//=NaN数字类型
if (num == NaN) {
  console.log('NaN');
} else if (num == 123) {
  console.log(123);
} else if (typeof num == 'number') {
  console.log('number');
}
else{
  console.log('str');
}
//='number'

3、考察输出

console.log(alert(1));/=undefined
/=原理:先执行alert,把alert执行的返回结果输出,alert没有返回结果,所以输出:undefined
typeof undefined; /=undefined
consloe.log(parseInt(undefined));/=NaN
isNaN(undefined);/=true

4、考察isNaN、parseInt、Number

  • parseInt、Number各自有规则;
  • isNaN:参照Number规则,先转数据为数字类型;
isNaN(null);/=false,null转为数字类型为0parseInt(null);/=NaN
isNaN(parseInt(null));/=true,相当于isNaN(NaN);
Number(null);/=0
parseInt("");/=NaN
Number("");/=0
isNaN("");/=false

5、考察基本数据类型

  • js中比较两个值:== 、===、ES6的Object.is
  • 规则:null==undefined为true,只要没有布尔、数字,都是转为字符串或对象比较;下方(十六、有详情)
  • ==:如果左右两边数据类型不同,则先转为相同类型,再进行比较;至于转为什么类型,谁转为谁有自己的规则;
  • 推测:只要有(Boolean)布尔类型、(Number)数字类型时,都转为数字类型比较;
  • 有字符串或引用类型就转为字符串比较;
isNaN(NaN) == "";
==>true == "";/=false
有布尔类型转数字比较;

6、关于<script>标签放在页面头部与尾部的区别,以及解决方法?

十三、条件判断、循环

1、js中常用判断语句

  • if 、else if 、else
  • 三元运算符:处理最简单的if else情况:x>10? x++:x--;
    • 情况1:如果不想处理一些情况,就用null、undefined占位,不占位会报错;x>10 ? x++ : null;
    • 情况2:如果要处理的一种情况需要做多件事,则用小括号包裹,并且每件事之间用逗号分隔;x>10 ? (x++,console.log(x)) : null;
  • switch case break:一个变量在不同情况下有不同操作时使用;
    • 每一种情况结束都要使用break不再向下执行,最后一个default就不需要加了,因为没有能再执行的了;
    • 每一步case都是按照===规则选择的;
    • switch(x){ case1:x += 1;break; }

2、for循环、for in循环

  • 循环:一轮一轮重复做某件事;循环一个集合,或控制循环次数;
  • 循环体中可能出现的关键字:
    • break:整个循环结束,当前循环有剩余代码也不执行,下一次i++也不执行;
    • continue:直接结束本轮循环,当前循环体下面代码不再执行,下一次i++正常执行;
  • for循环可以遍历\循环\迭代一个数组;因为数组有索引、length
  • for(var key in obj){} :遍历对象;
    • 当前对象有多少可枚举属性就循环多少次;
    • 每次循环属性名赋值给key;使用obj[key]获取当前属性值;注意不要使用obj.key、obj['key']获取
    • for in 循环的顺序会先按数字排序(如果属性名有数字),其他正常先后顺序;
var n = 10;
for (; n > 0;) {
  if(n>5){
    n-=2;
  }
  else{
    n-=3
  }
}
console.log(`${n}`);/= '-2 '

3、死循环,程序不输出

for(var i=3;i<10;i++){
	i--;
}
console.log(i);/= 没有输出

4、i++、i+=1、i=i+1

  • i++:默认为i=Number(i)+1;也是与其他两者的区别;
  • i+=1==i=i+1
let a = '10';
a == 10 ? a++ : a--;
console.log(a);/= 11

十四、DOM操作

DOM概念:文档对象模型,提供一系列属性和方法,让我们能操作页面中的dom元素;

1、获取DOM元素概念

  • 基于JS获取到的DOM元素是对象数据类型的值,里面包含很多浏览器自带的用来操作元素的键值对
    • 如:id:'box';存储元素的ID
    • style:{};存储当前元素的行内样式
    • 注意点:在设置行内样式的颜色时,使用基于16进制#fff、rgb表示写法时rgb(255 255 255),得到的是RGB形式,所以推荐写英文单词;
let box = document.getElementById('box');
---方式一:
box.style.color='red';/=可以修改,因为是操作堆内存
---方式二:
let boxSty = box.style;//指向样式对象
boxSty.color='red';/=可以修改,也是操作堆内存
---方式三:
let text = box.style.color;//指向""空字符串
text = 'red';/=不能修改,相当于给text赋值;

2、获取DOM元素常用方法

  • document.getElementById('box');:获取指定元素对象,在堆内存中;
  • document.getElementByTagName('li');:获取HTMLCollection元素集合(类数组),也是对象,内部每一项也是对象;

十五、函数

1、概念

  • 本质:把实现一个功能的代码封装起来,以后实现功能只需要执行函数,无需再写一遍代码;
  • 目的:封装;
  • 创建函数:生产洗衣机
    • function 函数名(形参1,...){}:参数规定放几件衣服,函数体规定怎么洗;
  • 执行函数
    • 函数名(实参1,...):放衣服开洗;

2、针对for循环产生的变量问题(var)

  • 解决一:自定义属性编程思想:解决for循环后的var i值问题;(没有兼容性问题)
for (let i = 0; i < itemList.length; i++) {
    var bgc = 'white',
        item = itemList[i];
    i%2 !== 0 ? bgc='pink':null;
    item.style.backgroundColor = bgc;
    item.myBg = bgc;//自定义属性
    item.onmouseover = function () {
      this.style.backgroundColor = 'green';
    }
    item.onmouseout = function () {
      this.style.backgroundColor = this.myBg;
    }
}
  • 解决二:闭包思想(没有兼容性问题)
for (let i = 0; i < itemList.length; i++) {
  (function (i) {
    var bgc = 'white',
        item = itemList[i];
    i%2 !== 0 ? bgc='pink':null;
    item.style.backgroundColor = bgc;
    item.onmouseover = function () {
      item.style.backgroundColor = 'green';
    }
    item.onmouseout = function () {
      item.style.backgroundColor = bgc;
    }
  })(i)
}
---另一种闭包形式
[].forEach.call(btnList,(item,index)=>{
	item.onclick = function(){
		alert(`当前点击按钮的索引为${index}`)
	}
})
  • 解决三:let声明变量(es6)–与闭包原理相似
for (let i = 0; i < itemList.length; i++) {
     let bgc = 'white',
         item = itemList[i];
     i%2 !== 0 ? bgc='pink':null;
     item.style.backgroundColor = bgc;
     item.onmouseover = function () {
       item.style.backgroundColor = 'green';
     }
     item.onmouseout = function () {
       item.style.backgroundColor = bgc;
     }
 }
  • 定义函数变量、函数声明、事件绑定都是只创建函数,此时函数中代码只是在堆内存中存储的字符串;

3、函数创建与执行的堆栈运行机制

  • 创建:形成新的堆内存
  • 执行:形成新的执行上下文栈内存;
  • 形参:创建函数时设定的变量,对应实参不传就是undefined;
  • 实参:执行函数时给形参传递的具体值,可以是变量、具体值、表达式,最终传进去的都是最终值(js数据类型);

4、形参、实参

  • 指定数求和:function(x,y,z,...){}有几个数,用几个形参接收;
  • 任意数求和:不确定实参个数,所以没法设置形参个数;
    • 实参集合(箭头函数中没有):function(){ console.log(arguments) };是类数组,与HTMLCollcetion类似;通过for循环使用;
    • es6的剩余运算符:function(...args){ console.log( args ) }

5、函数返回值return

  • return;:下面代码不再执行;
  • return [变量、函数]:返回函数内部私有的变量,外部得到的是这个变量的值,需要外部定义新的变量接收(或者直接使用);
function sum(){
	let a = 1;
	return a
}
var aa = sum();/函数中不写return,返回undefined
console.log(aa);/=1

6、函数类型

  • 实名函数:function func(){}
  • 匿名函数:
    • 函数表达式:var func = function(){}
    • 立即执行函数:(function(n){})(n)
    • 箭头函数:var func = ()=>{}

十六、数据类型间比较的规则

1、==的比较规则

  • 左右两边数据类型不同时,转为统一类型;哪到底转成什么类型?
相同类型间:
NaN == NaN; /= false; NaN 跟任何值都不相等
Infinity == Infinity; /=true; 只和自己想等
Symbol(1) == Symbol(1); /=false; Symbol() 跟任何值都不相等
对象 == 对象; /= 比较地址,相等true,不等false
---
不同类型间:
null == undefined; /=true;除此之外,它们和任何值都不相等;
对象 == 字符串; /= 对象转为字符串
除此以上情况外,都转为 数字进行比较。
(只要没有布尔、数字,都是转为字符串或对象比较)

十七、数组

特殊的对象,属性名是索引;有length属性;

1、一维数组、多维数组

一维:let arr = [1,2,3];
二维数组:子项也可以展开
let arr = [1,{a:1}];
let arr = [1,[1,2]]

2、需要掌握

  • 基础操作
    • arr[arr.length] = 1;数组末尾追加;
    • for( let i=0;i<arr.length;i++ ){};遍历索引
    • for( let index in arr ){};遍历属性名(索引)
    • for( let item of arr ){};遍历属性值
    • 删除:delete arr[0];但是数组长度不变,删除项为空,所以一般不用这种方式;
    • 删除最后一项:arr.length--
  • 内置方法(浏览器自带的方法)
  • 排序、去重(算法)
  • 扁平化、深度克隆
    • 扁平化:数组的扁平化指将一个多维数组变为一维数组
    • [1, [2, [3, 4]]]--->[1, 2, 3, 4]
如果只有两层:let array = [1, [2, 3, 4]];
方法一:
function flatten(arr) {
  return Array.prototype.concat.apply([], arr); /= apply第二个参数就是数组形式
}
方法二:
function flatten(arr) {
    while(arr.some(item=>Array.isArray(item))) {
        arr = [].concat(...arr);
    }
    return arr;
}
console.log(flatten(array));
多层:let arrayDeeper = [1, [2, [3, 4]]];

方式一:toString&split&map方法
function flattenDeeper(arr){
  return arr.toString().split(',').map((item)=>parseInt(item))
} /=map方法将字符串转为数字类型

方式二:reduce&concat方法
function flattenDeeper(arr) {  
    return arr.reduce((result, item)=> {
        return result.concat(Array.isArray(item) ? flattenDeeper(item) : item);
    }, []);
}

方法三:join&split&map方法
function flattenDeeper(arr){
  return arr.join().split(',').map((item)=>parseInt(item))
}
let arr1 = [1,[2,3,[4,5]]]
console.log(flattenDeeper(arr1))//[1,2,3,4,5]

3、常见内置方法

  • 记忆方式:
    • 方法的意义和作用
    • 参数
    • 返回值
    • 原始数组是否改变
  • 1、关于数组的增删改
数组方法作用参数返回值原数组是否改变
push数组末尾追加元素参数个数、类型不固定新增数组的长度改变
pop数组末尾删除一个元素被删除的末尾数组元素改变
unshift数组开头追加元素参数个数、类型不固定新增数组的长度改变
shift数组开头删除一个元素被删除的开头数组元素改变
splice实现数组指定位置的增删改删:arr.splice(n,m),从索引n开始删m项
增:arr.splice(n,0,x,..)
改:arr.splice(n,m,x,..),从索引n开始删m项,用新元素替换
被删元素组成的数组;没有删除的返回[]都改变
  • 2、关于查询和拼接
数组方法作用参数返回值原数组是否改变
slice从数组中查询元素;浅克隆let newArr = arr.slice(n,m)从索引n开始,查到索引m的前一项返回一个新数组,包含查询到的元素不改变
concat实现数组拼接;浅克隆let newArr = arr.concat('aa',arr1)传具体值、要连接的数组返回连接后的新数组不改变,目标数组也不改变
  • 3、关于数组转为字符串
数组方法作用参数返回值原数组是否改变
toString将数组转为字符串,以逗号分隔返回字符串不改变
join将数组转为字符串,以指定符号分隔arr.join('-'),指定分隔符,不写默认,逗号返回字符串不改变
  • 4、关于包含、排序
数组方法作用参数返回值原数组是否改变
indexOf查询指定元素首次出现的索引arr.indexOf(item,start)
所查元素内容,开始查询的位置
返回Number类型,查到则为第一次出现位置的索引;没有查到返回-1不改变
lastIndexOf查询指定元素最后出现的的索引array.lastIndexOf(item,start)所查元素内容,开始查询的位置返回Number类型,查到为最后一次出现位置的索引;没有查到返回-1不改变
includes判断一个数组是否包含一个指定的值arr.includes(searchElement, fromIndex)要查询的元素,开始位置返回布尔类型值;
包含:true;不包含:false
不改变
reverse(排序)用于颠倒数组中元素的顺序返回颠倒后的原数组改变
sort(排序)按规则排序数组函数规则返回改变后的原数组改变
  • 5、关于数组中迭代方法
数组方法作用参数返回值原数组是否改变
forEach遍历数组中每一项,可得到当前项值与索引函数参数
arr.forEach(function(item,index){})
undefined,处理函数中return无效不改变
map遍历数组中每一项,可得到当前项值与索引函数参数
let newArr = arr.map(function(item,index){ return item*2 })
返回处理后新数组
每一项返回值由return决定;
不改变
  • 扩展:数组每项求和
let arr = [100,200,300];
let total = 0;
// --for循环
// for(var i=0;i<arr.length;i++){
//   total += arr[i]
// }

// --for of循环
// for(let item of arr){
//   total += item
// }

// --转字符串
// var str = arr.join('+');
// total = eval(str)

// --es6的reduce
total = arr.reduce((pre,item)=>{
  return pre += item
},0)
console.log(total);

4、数组去重(12种)

  • 双for循环(有问题)
    • 问题:数组塌陷(数组元素减少时导致的后面元素前移)
    • 原因:splice删除是直接删除原数组,所以每删除一项会导致后面数据前移,索引发生变化,如果不用j--,就会产生每次删除后再循环时就会隔过去一项数据元素;
    • 解决:每次删除后随即调用j--,用来与下次循环的j++抵消;
    • 优化splice删除优化(让后面每一项前移太耗性能),不在当前项删除,而是用最后一项替换这一项,把最后一项删除,因为本来就是为了去重,不考虑原有顺序问题;
let arr = [1,2,3,2,3,4,5,2,3,4,2,1,3,2,4];
for(let i=0;i<arr.length-1;i++){
  let item = arr[i];
  for(let j=i+1;j<arr.length;j++){
    if(arr[j]===item){
      arr.splice(j,1);==>改进:arr[j] = arr[arr.length-1];arr.length--;或arr.pop()
      j--;/= 解决splice删除引发的数组塌陷问题
    }
  }
}
console.log(arr);
  • 对象的键值对方式
    • 弊端:去重数组中不能包含对象、函数,因为属性名不能为这些;而且数字与字符串一样的值也会认为重复;多个undefined不会去重;
    • 优点:单循环,性能好点
:将数组每一项当做对象的键与值;如果属性名存在那当前项就是重复的。
let arr = [1,2,3,1,1,4]
let obj = {}
for(let i=0;i<arr.length;i++){
  let item = arr[i]
  if(obj[item] !== undefined){
    arr[i] = arr[arr.length-1] /=这是改进写法,将最后一项的值拿过来,删除最后一项
    arr.length--;  /= 属性值不是undefined,就删除数组中这项
    i--;
    continue;
  }
  obj[item] = item;/= 属性值是undefined就正常存对象里,数组中不删
}
console.log(arr);/= [ 1, 2, 3, 4 ]
  • Set数据结构:类似数组
let arr = ['a','a','b',1,2,1];
const set = new Set(arr);/=伪数组 Set(4) {"a", "b", 1, 2};有size属性替换length;
转真正数组:
const newArr = [...set];
或者const newArr = Array.from(set);
console.log(newArr);//[ 'a', 'b', 1, 2 ]

》》下一个,十八:字符串

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值