一、js数据类型
- 基本数据类型:String、Number、Boolean、null、undefined、Bigint、Symbol
- 引用数据类型:Object、Function、Array、Date
二、typeof 和 instanceof
typeof
- typeof null 返回 “object”
- typeof 对于引用类型 除了function 会返回function 其他的都是object 对于基本类型 typeof null 为object 其他的都是正常的
- typeof Array(Array是构造函数 所以返回function) 如果是实例就是对象了
原因:当时,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),完全没考虑null,只把它当作object的一种特殊值,32位全部为0。 这是typeof null返回object的根本原因。在js中 二进制的前三位来进行数据类型判断 Object的前三位都是0 null全0 所以就是返回Object
instanceof
三、let、const、var 区别
- var 存在变量提升,const、let不存在变量提升
- var 可以重复声明 const、let不可重复声明 且 const 初始化必须赋值 后续不可更改 对象可以改变其中的属性或属性值
- var 是全局作用域、let和const是块级作用域
- let 和 const 存在暂时性死区 因为变量不可提升
- 在函数里面 声明变量不使用关键词 会是全局变量
四、判断一个值的类型
- 对于基本类型 ,可以使用 typeof 但是null会返回object
- 对于引用类型 ,除了typeof function 返回 function 其余都是 object 因此对于引用类型 使用instanceof
- 最全面的 :Object.prototype.toString.call(arg) // 判断arg的类型
五、null 和 undefined 的区别
-
null表示定义了且赋值为null
-
undefined表示定义了但没赋值
六、数组的相关方法
-
Array.from() // 将类数组转化成数组
- str.split(“,”) 以逗号切割str字符串 返回一个数组 和arr.join(“,”) 相反的效果
let arr = [2, 3, 1, 4]; let addFromEnd = arr.splice(0, 1); //包含开始元素 返回被删除的元素 console.log(arr); //[3,1,4] console.log(addFromEnd); //[2]
let arr = [2, 3, 1, 4]; let addFromEnd = arr.splice(1, 1, 5, 6); //包含开始元素 返回被删除的元素并从此位置替换要加入的内容 console.log(arr); //[2,5,6,1,4] console.log(addFromEnd); //[3]
let arr = [2, 3, 1, 4]; let addFromEnd = arr.splice(1, 0, 5, 6); //从下标为1开始包括下标 添加元素5,6 console.log(arr); //[ 2,5,6,3,1,4] console.log(addFromEnd); //[]
// arr.fill(value,start,end) start和end是可选项 都不设置则是全部填充值 let arr=new Array(3); arr.fill(0) // 全部填充0 arr.fill(1,0,2) // 范围 :0-1下标 不包括2 console.log(arr);
let arr=[1,2,3,4,5]; let newarr=arr.slice(2,4); console.log(newarr); // [3,4]
{ let arr = [1, 2, 3, 4] let b = arr.join('-') //可选拼接参数 console.log(b)//1-2-3-4 console.log(typeof b)//string }
{ let arr = [1, 2, 3, 4, 5, 6] console.log(arr.indexOf(3))//2 console.log(arr.indexOf(3, 3))//-1 第一个参数为查找的值 第二个参数为查找的起始位 console.log(arr.indexOf(8))//-1 }
{ let arr = [1, NaN, 100, '42']; console.log(arr.includes(1)); //true console.log(arr.includes(NaN)); //true console.log(arr.includes(1, 3)); //false }
let arr = [22, 33, 44, 55]; arr.forEach((value, index, arr) => { console.log("value:" + value); console.log("index:" + index); console.log(arr); });
{ let arr = [1,2,3,4,5] let result = arr.filter(item=> item>2) console.log(result)//[3, 4, 5] }
{ let arr = [1,2,3,4,5] let result = arr.map(item=> item*2) console.log(result)//[ 2, 4, 6, 8, 10 ] } arr.map((item,index,arr)=>{ }) // item 是每一项数组的值 index是数组索引 arr是数组
{ let arr = [1, 2, 3, 4, 5]; let result = arr.reduce((pre, current) => { return pre + current; }, 10); console.log(result); //10+1+2+3+4+5 10为传入的初始值 }
案例:
{ let arr = ["钱", "钱", "钱", "钱", "富", "林"]; let arr2 = arr.reduce((prev, cur) => { if (cur in prev) { prev[cur]++; } else { prev[cur] = 1; } return prev; }, {}); Object.keys(arr2).forEach((item) => { console.log(item, arr2[item]); }); //钱 4 //富 1 //林 1 }
七、原型和原型链
相关概念
-
实例的隐式原型指向构造函数的显式原型
-
const a=new A() a.__proto__=A.prototype;
原型链:
当调用某种方法或者属性时,首先会在自身调用和查找,如果自身没有,就会去它的proto属性中查找,之后会去当前实例所属类的prototype原型对象查找,如果原型对象上也没有 ,由于原型对象上也有proto属性,因此又会重复上述查找方法 Object的原型也就是null 这就是原型链的尽头
- 原型链式基于隐式原型查找
- 万物皆可对象 定义在对象原型上的属性 在对象类的原型链中都可以找到 例:
var f = new Function();
var f1 = new f();
Object.prototype.a = 123; // Object原型上的属性可以访问
Function.prototype.b = 234;
console.log(f1.a); // 123
console.log(f1.b); //undefined
console.log(f.b); // 234
八、JS中的同源策略
同源:同协议、同域名、同端口
同源策略:不同的客户端脚本(javascript,ActionScript)在没有授权的情况下,不能读取对方资源。简单来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。
同源策略是浏览器最核心最基本的安全功能 如果缺少了同源策略,浏览器的核心功能会受到影响
解决跨域问题的方法:
九、js的内存回收机制
内存泄漏:不再用到的内存,没有及时释放 ,就叫做内存泄漏
垃圾回收机制:
- 标记清除 是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。
- 引用计数 跟踪记录每个值被引用的次数。
引起内存泄漏:
- 意外的全局变量 解决:严格模式
- 闭包 解决:可以接触闭包或者删除对这个闭包的引用
- 没有清理的DOM元素引用
- 被遗忘的定时器或者回调
十、this指向问题
面向对象语言中 this 表示当前对象的一个引用。
对于函数内部的this指向 做以下判断
this在非严格模式下默认指向 window 严格模式下 undefined
- 查看函数在哪被调用。
- 点左侧有没有对象?如果有,它就是 “this” 的引用。如果没有,继续第 3 步。
- 该函数是不是用 “call”、“apply” 或者 “bind” 调用的?如果是,它会显式地指明 “this” 的引用。如果不是,继续第 4 步。
- 该函数是不是用 “new” 调用的?如果是,“this” 指向的就是 JavaScript 解释器新创建的对象。如果不是,继续第 5 步。
- 是否在“严格模式”下?如果是,“this” 就是 undefined,如果不是,继续第 6 步。
- JavaScript 很奇怪,“this” 会指向 “window” 对象。
十一、函数提升和变量提升
注:函数提升只会提升函数声明 不会提升函数表达式
函数声明: function add(){}
函数表达式:var add=function(){}
-
函数声明大于变量声明
-
如果仅是定义没有赋值 就不会覆盖之前的变量或者函数 例:
-
function f(x){ var x; // 虽然定义了变量 但没赋值 所以不会覆盖 console.log(x) // 5 而不是 undefined } f(5)
-
如果函数声明和变量声明同名 但是都没赋值 则优先指向 函数声明 若有赋值就覆盖(覆盖的原因还是变量提升 函数提升的原因)
十二、JSON
json是一种文本格式 不属于任何一种语言 json可以理解为用来传输的文本
Json转化为js对象 :JSON.parse(json);
js对象转化为Json:JSON.stringify(js);
十三、defer 和 async
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yUuDKxo5-1649146282841)(E:\各学习知识点总结\typora图片\image-20220305094921188.png)]
异步一般适合于不操作DOM的脚本
对于有操作DOM的脚本 采用推迟比较好
理解:推迟 就是假设a,b两个进程异步加载 但是 b进程必须等到a进程加载完后才会执行 而异步 是谁先加载块 谁先执行
十四、事件捕获和事件冒泡
DOM事件流:事件捕获阶段 ->处于目标阶段 -> 事件冒泡阶段
- 事件捕获优先于事件冒泡
- addEventListerner 默认false 事件冒泡 true 事件捕捉
- e.currentTarget是事件捕获到的当前元素。 e.target,事件元素 触发的元素
阻止冒泡:
1、 在相应的处理函数内,加入 event.stopPropagation() ,终止事件的广播分发,这样事件停留在本节点,不会再往外传播了
2、在自身处理函数中加入判断
document.getElementById("box1").addEventListener("click",function(event){
if(event.target == event.currentTarget) // 判断触发的事件是不是本省
{
alert("您好,我是最外层div。");
}
});
3、事件委托
我们把本来每个元素都要有的处理函数,都交给了其祖父节点body 元素来完成了,也就是说,span,div2,div1 将自己的响应逻辑委托给body,让它来完成相应逻辑,自己不实现相应逻辑,这个模式,就是所谓的事件委托
<script type="text/javascript">
window.onload = function() {
document.getElementById("body").addEventListener("click",eventPerformed);
}
function eventPerformed(event) {
var target = event.target;
switch (target.id) {
case "span":
alert("您好,我是span。");
break;
case "div1":
alert("您好,我是第二层div。");
break;
case "div2":
alert("您好,我是最外层div。");
break;
}
}
</script>
十五、JS模块规范
AMD、CMD、CommonJS、UMD、ESM( JS模块化规范)
十六、严格模式
在严格模式下,在全局执行上下文的this和全局执行上下文的函数内this不再指向window对象;
变量必须先声明再使用,不存在变量提升;
var声明的变量不允许重复声明同一个变量。
不允许使用未声明的变量。对象也是一个变量。
不允许对变量或函数使用delete操作符不允许变量重名
不允许使用八进制
禁止this关键字指向全局对象不可在if内部声明函数
十七、== 比较注意事项
相等和不相等——先转换再比较 (==)
对于相等和不相等操作符:在JS高程中一书中给出如下的基本转换规则
①、如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换为0,而true转换为1;
②、如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
③、如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较
这两个操作符在进行比较时则要遵循下列规则。
①、null 和undefined 是相等的
②、要比较相等性之前,不能将null 和 undefined 转换成其他任何值
③、如果有一个操作数是NaN,则相等操作符返回 false ,而不相等操作符返回 true。重要提示:即使两个操作数都是NaN,相等操作符也返回 false了;因为按照规则, NaN 不等于 NaN
④、如果两个操作数都是对象,则比较它们是不是同一个对象,如果两个操作数都指向同一个对象,则相等操作符返回 true;否则, 返回false
十八、箭头函数特点
- 箭头函数是匿名函数
- 不能作为构造函数 不能使用new
- 没有arguments 用rest参数代替
- 箭头函数没有原型对象
- 对于参数和函数体可以省略
- 箭头函数不绑定this关键字 箭头函数中的this指向的是函数定义位置的上下文this
// 箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
const obj = {name:"Axx",age:19};
const fn = () => {
console.log(this); //window
}
fn.call(obj); // this指向还是window,因为箭头函数没有自己的this
function fn2(){
console.log(this); // fn2普通函数this指向obj
return () => {
console.log(this); //object
}
}
// 此时箭头函数的this指向obj,因为箭头函数处于fn2函数体当中,而fn2的this指向的是obj,因此箭头函数的this也指向obj
fn2.call(obj)();
箭头函数不绑定this关键字 箭头函数中的this指向的是函数定义位置的上下文this
// 箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
const obj = {name:"Axx",age:19};
const fn = () => {
console.log(this); //window
}
fn.call(obj); // this指向还是window,因为箭头函数没有自己的this
function fn2(){
console.log(this); // fn2普通函数this指向obj
return () => {
console.log(this); //object
}
}
// 此时箭头函数的this指向obj,因为箭头函数处于fn2函数体当中,而fn2的this指向的是obj,因此箭头函数的this也指向obj
fn2.call(obj)();