判断数据类型最准确语法
Object.prototype.toString.call(数据)
常用方法
1.join:array.join(‘符号’) 把数组转为字符串,不改变原数组
var arr1 = [1, 2, 'wew', 100]
var res1 = arr1.join()
var res1_1 = arr1.join("**")
console.log("res1-join-无参数", res1)
//res1-join-无参数 1,2,wew,100
console.log("res1-join-有参数", res1_1)
//res1-join-有参数 1**2**wew**100
console.log("join是否更改原数组", arr1);
//join是否更改原数组 (4) [1, 2, 'wew', 100]
2.split:string.split(‘符号’) 以字符串为标准进行分割字符串,返回数组
console.log("split返回", "a%h%jk%iuhfi".split("%"));
//split返回 (4) ['a', 'h', 'jk', 'iuhfi']
3.push:array.push(参数),把参数添加到数组尾部,改变原数组,此方法返回最新的数组长度为数字
var arr2 = [1, 2, 3, 4, 5, 6]
var res2 = arr2.push(50)
console.log("res2-push", res2);
// res2-push 7
console.log("arr2-是否改变", arr2);
// arr2-是否改变 (8) [1, 2, 3, 4, 5, 6, 50]
4.pop删除数组尾部的一个元素,改变原数组,此方法返回删除的那个元素
var res3 = arr2.pop(50)
console.log("res2-pop", res3);
//res2-pop 50
console.log("arr2-是否改变", arr2);
// arr2-是否改变 (8) [1, 2, 3, 4, 5, 6]
5.unshift:array.unshift(参数),把参数添加到数组头部,改变原数组,此方法返回最新的数组长度为数字
var res3 = arr2.unshift(100)
console.log("res2-unshift", res3);
//res2-unshift 7 长度为7
console.log("arr2-是否改变", arr2);
//arr2-是否改变 (7) [100, 1, 2, 3, 4, 5, 6]
6.shift:删除数组头部的一个元素,改变原数组,此方法返回删除的那个元素
var res3 = arr2.shift()
console.log("res2-shift", res3);
//res2-shift 100
console.log("arr2-是否改变", arr2);
//arr2-是否改变 (6) [1, 2, 3, 4, 5, 6]
7.reverse:反转数组,更改原数组
var arr4 = [1, 2, 3, 4, 5, 6]
var res4 = arr4.reverse()
console.log("reverse-结果", res4);
// reverse-结果 (6) [6, 5, 4, 3, 2, 1]
console.log("arr4-是否改变", arr4);
// arr2-是否改变 (6) [6, 5, 4, 3, 2, 1]
8.sort:排序,sort((a,b)=>{reture a-b})
默认a<b
return 数字
<0 升序
>0 降序
更改原数组,返回当前更改数组
var arr5 = [1, 2, 4, 8, 50, 9, 7, 20]
var res5 = arr5.sort((a, b) => { return a - b })
console.log('升序', res5);
// 升序 (8) [1, 2, 4, 7, 8, 9, 20, 50]
console.log("arr5-是否改变", arr5);
// arr5-是否改变 (8) [1, 2, 4, 7, 8, 9, 20, 50]
var res5 = arr5.sort((a, b) => { return b - a })
console.log('降序', res5);
// 降序 (8) [50, 20, 9, 8, 7, 4, 2, 1]
console.log("arr5-是否改变", arr5);
// arr5-是否改变 (8) [50, 20, 9, 8, 7, 4, 2, 1]
9.concat:数组拼接 array1.concat(arr2);不更改原数组,返回拼接后的新数组
var arr6 = [1, 2]
var arr6_1 = [5, 6]
var res6 = arr6.concat(arr6_1)
console.log('concat-结果', res6);
// concat-结果 (4) [1, 2, 5, 6]
console.log('concat-原数组', arr6_1, arr6);
// concat-原数组 (2) [5, 6] (2) [1, 2]
10.splice:截取/删除数组,3个参数非必填
array(‘开始截取的数组的下标’,‘截取的长度’,‘填充替换的数组’)
更改原数组,返回删除的数组数据
var arr7 = [1, 2, 3, 4, 5, 6]
var res7 = arr7.splice(2, 2)
console.log('splice-结果', res7);
// // splice-结果 (2) [3, 4]
console.log('splice-原数组', arr7);
// splice-原数组 (4) [1, 2, 5, 6]
var res7 = arr7.splice(2, 2, '替换内容')
console.log('splice-原数组', arr7);
// splice-原数组 (5) [1, 2, '替换内容', 5, 6]
11.slice:截取/删除数组,不更改原数组
array.slice(“开始截取的数组下标”,“结束截取数组的下标并且不包含”)
var arr8 = [1, 2, 3, 4, 5, 6]
var res8 = arr8.slice(2, 4)
console.log('slice-结果', res8);
// slice-结果 (2) [3, 4]
console.log('slice-原数组', arr8);
// slice -原数组 (6) [1, 2, 3, 4, 5, 6]
常用数组方法
var userList = [
{ uname: '小红1', uage: 11 },
{ uname: '小红2', uage: 12 },
{ uname: '小红3', uage: 13 },
{ uname: '小红4', uage: 14 },
{ uname: '小红5', uage: 15 },
]
forEach 数组里面每一项进行操作 , 没有返回值并不会被打破 return没有意义
userList.forEach(el => {
el.class = '一年级'
})
console.log("foreach", userList);
map 为数组里面每一项进行操作 并返回一个新数组, 新数组为map的 return 结果
var res2 = userList.map(el => {
if (el.uage > 12) {
return el
}
}).filter(el => el)
console.log("res2_map", res2);
filter 循环过滤符合条件的数组,返回一个新数组
var res3 = userList.filter(el => {
// return true的时候该元素被返回
return el.uage > 13
})
console.log("res3-filter", res3);
find查找符合条件的元素返回 只会返回符合条件的第一个
return true的时候该元素被返回
var res4 = userList.find(el => {
return el.uage > 13
})
console.log("res4-find", res4);
findindex 查找符合条件的元素返回 只会返回符合条件的第一个
return true的时候该元素被返回
var res5 = userList.findIndex(el => {
return el.uage > 12
})
console.log("res5-find", res5);
some需求 如果年龄有大于12岁,就需要加钱
var res6 = userList.some(el => el.uage > 10)
if (res6) {
alert('加钱')
}
every需求 如果class 有一个不等于一年级,就加钱
userList[0].class = ''
var res6 = userList.every(el => el.class == '一年级')
if (!res6) {
alert('加钱')
}
reduce 累加
var arr1=[1,2,3,4,5,6]
var res11=arr1.reduce((p,n)=>p+n)
console.log('reduce累加',res11);
浅拷贝和深拷贝
传址,传值,内存堆栈的一个知识点
复杂数据类型
浅拷贝:复杂数据类型的传址(两个变量指向一个数据)
深拷贝:完全赋值一份数据一致的非同一个地址的数据(两个数据不同地址)
浅拷贝
var obj1 = {
a: 1,
b: 2
}
var obj2 = obj1
obj2.c = 3;
console.log('obj1', obj1);
console.log('obj2', obj2);
深拷贝
1.JSON.parse(JSON.stringify(obj))//变字符串后变对象开辟新空间
缺点:undefined和函数无法赋值
var newObj = {
a: 1,
b: 2,
list: [1, 2, 3],
sbjt: {},
c: undefined,
d: () => { }
}
var newObj2 = JSON.parse(JSON.stringify(newObj))
newObj2.hi = '你好'
console.log('newObj', newObj);
console.log('newObj2', newObj2);
最常用的深拷贝方法是用递归进行拷贝
var oneObj = {
a: 1,
b: 2,
list: [1, 2, 3],
sbjt: {},
list2: [
{
deep1: '!!!'
}
],
c: undefined,
d: () => {
alert('你好')
}
}
function deep(obj) {
// 判断数据类型是否是数组/对象 进行新数据声明
// 新建一个新的地址
if (!(obj instanceof Object || obj instanceof Array)) { return obj }//判断简单数据类型
var targetObj = obj instanceof Array ? [] : {}
// 循环obj
for (const key in obj) {
// 忽略从原型继承的属性,不进行拷贝
if (obj.hasOwnProperty.call(obj, key)) {
const value = obj[key];//对应的value
// 判断value 是否是数组对象
if (value instanceof Array || value instanceof Object) {
targetObj[key] = deep(value)
} else {
targetObj[key] = value
}
}
}
return targetObj
}
var twoObj = deep(oneObj)
twoObj.list2[0].deep1 = '@@@@@@@'
console.log('oneObj', oneObj);
console.log('twoObj', twoObj);
this 指向
.之前就是this
function fun1() {
console.log('fun1->this', this);
}
fun1()//window.fun1()
var obj = {
fun2: function () {
console.log('fun2->this', this);
console.log('fun2->this', this === obj);
},
obj2: {
fun3: function () {
console.log('fun3->this', this);
console.log('fun3->this', this === obj.obj2);
}
}
}
obj.fun2()
// fun2->this true
obj.obj2.fun3()
// fun3->this true
//**** 普通函数的this是执行的时候绑定 箭头函数是声明的时候进行绑定this
//es6 箭头函数,箭头函数里面指向是声明的当前上下文环境,并且不可改变this指向
var obj3 = {
oson1: {
oson2: {
fun1: () => {
console.log('箭头函数this', this);
},
fun2: function (p1, p2) {
console.log('普通函数this', this);
console.log('普通函数改变this---参数', p1, p2);
}
}
}
}
obj3.oson1.oson2.fun1()
obj3.oson1.oson2.fun2()
//改变this指向的三个方法的区别:apply,call,bind
/*
1.apply 改变this指向并立即执行函数,参数以数组形式写
2.call 改变this指向并立即执行函数,参数逗号分割
3.bind 语法和call一样,但是改变完不会立即执行
*/
obj3.oson1.oson2.fun2.apply({ a: 123 }, ['A', 'B'])
obj3.oson1.oson2.fun2.call({ a: 456 }, 'C', 'D')
obj3.oson1.oson2.fun2.bind({ a: 789 }, 'E', 'F')()
// 例如:按钮点击事件 call立即执行 bind点击后执行
构造函数
构造函数(普通函数,约定构造函数的函数名首字母大写)
function Fun1(name) {
this.name = name
this.logfun = function () {
console.log('hello', this.name);
}
}
/*
1.创建一个对象,指向构造函数的this (this不在指向window)
2.this的__proto__指向构造函数的prototype
3.执行构造函数
4.返回:
如果没有return 或者 return的是简单数据类型,忽略 直接return this
如果return的是复杂数据类型则返回的是当前return的值
*/
var obj = new Fun1('木木')
obj.logfun()
console.log('obj', obj);
console.log('是否是相等的obj', obj.__proto__ === Fun1.prototype);
console.log('-----------------------');
异步解决方案
//定时器
function funyb() {
var res;
setTimeout(() => {
res='你好'
}, 100);
console.log('res',res);
}
funyb()
callbakc
// callbakc
function funback(callback) {
setTimeout(() => {
callback('callback结果')
}, 100);
}
funback((res) => {
console.log('callback函数', res);
})
Promise
// Promise 有三种状态,pending=>转换成两个状态resolve/reject
function p1() {
return new Promise((resolve, reject) => {
resolve('成功结果')
// reject('失败结果')
})
}
p1().then((res) => {
console.log('promise', res);
}).catch((err) => {
console.log('promise', err);
})
Promise.all
// Promise.all 多个异步执行结果
function pone() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('1111111111')
}, 100);
})
}
function ptwo() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3])
}, 100);
})
}
// 参数为Promise对象组成的数组
Promise.all([pone(), ptwo()]).then((res) => {
console.log('Promise all', res);
}).catch((err) => {
// 返回最近的一个错误
console.log('Promise all', err);
})
async/await
function funasc(params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve([1, 2, 3])
}, 100);
})
}
// async可以单独使用 并且返回的是promise对象
// await (后面跟的是个异步/promise)必须配合async使用,不然会报错
async function getdata() {
const res = await funasc()
console.log('res', res)
}
getdata()
原型链
// prototype 这个属性只有函数对象才有!,(构造)函数的原型对象 一定返回一个对象
// __proto__ 所有对象都有此属性,总是指向对应的(构造)函数的原型对象/ prototype
// constructor: __proto__下面的constructor指向构造函数自己
// 对象访问属性的时候,在自身属性查找,找不到再去__proto__原型链上查找,直到找不到为止返回undefined
// 原型链的终点 Object.prototype
function Yxl(name) {
this.name = name
}
Yxl.prototype.age = 10;
const msgone = new Yxl('嘻嘻')
const msgtwo = new Yxl('哈哈')
console.log('msgone', msgone);
console.log('msgtwo', msgtwo);
console.log('msgone', msgone.name);
console.log('msgtwo', msgtwo.name);
console.log('msgone', msgone.age);
console.log('msgtwo', msgtwo.age);
// constructor 主要判断对象的原型是否是某个对象
console.log('Yxl-Object',msgone.__proto__.__proto__===Object.prototype);
console.log('Yxl-constructor',msgone.__proto__.constructor===Yxl);
console.log('Yxl-constructor',msgone.__proto__.__proto__.constructor===Object);
闭包
// 函数套函数,并把内部函数return,内部函数可以访问外部函数的变量,一级级向上找
// 内部函数访问父函数的变量的最终结果
// 作用:封装变量,收敛权限
// 优点:不会造成变量污染
// 内存:垃圾回收机制:当一个变量在作用于内部不再被使用,会被内存释放
// 闭包被子函数引用的变量不会被回收,有可能造成内存泄漏(缺点)
var a=1
var b=2
function fun1(){
var a=111
console.log('父函数aaaaa',a);
console.log('父函数bbbbb',b);
function funzi(){
console.log("子函数aaaaa",a);
}
funzi()
}
a=1000
function fun2(){
;console.log('fun2 aaaaaa',a);
}
fun2()
fun1()