日期
//获取日期之间的日期数组
Date.prototype.format = function() {
var s = '';
var mouth = (this.getMonth() + 1) >= 10 ? (this.getMonth() + 1) : ('0' + (this.getMonth() + 1));
var day = this.getDate() >= 10 ? this.getDate() : ('0' + this.getDate());
s += this.getFullYear() + '-'; // 获取年份。
s += mouth + "-"; // 获取月份。
s += day; // 获取日。
return(s); // 返回日期。
};
function getAll(begin, end) {
var dateArr=[];
var ab = begin.split("-");
var ae = end.split("-");
var db = new Date();
db.setUTCFullYear(ab[0], ab[1] - 1, ab[2]);
var de = new Date();
de.setUTCFullYear(ae[0], ae[1] - 1, ae[2]);
var unixDb = db.getTime();
var unixDe = de.getTime();
for(var k = unixDb; k <= unixDe;) {
dateArr.push((new Date(parseInt(k))).format());
k = k + 24 * 60 * 60 * 1000;
}
console.log(dateArr);
}
/**
* 根据日期字符串获取星期几
* @param dateString 日期字符串(如:2020-05-02)
* @returns {String}
*/
function (dateString) {
var dateArray = dateString.split("-");
let date = new Date(
dateArray[0],
parseInt(dateArray[1] - 1),
dateArray[2]
);
let weekList = ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"];
return weekList[date.getDay()];
},
防抖(在第一次触发事件时,不立即执行函数,而是给出一个期限值比如200ms)
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay) // 简化写法
}
}
// 然后是旧代码
function showTop () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = debounce(showTop,1000) // 为了方便观察效果我们取个大点的间断值,实际使用根据需要来配置
节流(即使用户不断拖动滚动条,也能在某个时间间隔之后给出反馈呢)
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
/* 请注意,节流函数并不止上面这种实现方案,
例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。
也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样
*/
// 以下照旧
function showTop () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop,1000)
js继承
//es5实现
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function() {
return this.name;
}
function Child(name, age) {
//借用构造函数
Parent.call(this, name);
this.age = age;
}
//实现继承
Child.prototype = new Parent();
Child.prototype.constructor = Child;//Child.prototype的指向发生改变,需修正
Child.prototype.getAge = function(){
return this.Age;
};
var people = new Child("lily", 20);
console.log(people.getName());
//语法糖------------------------------------------------------------------------------------------------
class Parent {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
getAge() {
return this.age;
}
}
const people = new Child("lily", 20);
console.log(people.getName());
// es6继承------------------------------------------------------------------------------------------------
class Animal {
//构造函数,里面写上对象的属性
constructor(props) {
this.name = props.name || 'Unknown';
}
//方法写在后面
eat() {//父类共有的方法
console.log(this.name + " will eat pests.");
}
}
//class继承
class Bird extends Animal {
//构造函数
constructor(props,myAttribute) {//props是继承过来的属性,myAttribute是自己的属性
//调用实现父类的构造函数
super(props)//相当于获得父类的this指向
this.type = props.type || "Unknown";//父类的属性,也可写在父类中
this.attr = myAttribute;//自己的私有属性
}
fly() {//自己私有的方法
console.log(this.name + " are friendly to people.");
}
myattr() {//自己私有的方法
console.log(this.type+'---'+this.attr);
}
}
//通过new实例化
var myBird = new Bird({
name: '小燕子',
type: 'Egg animal'//卵生动物
},'Bird class')
myBird.eat()
myBird.fly()
myBird.myattr()
js获取dom节点的方式
- 通过ID获取(getElementById)
- 通过name属性(getElementsByName)
- 通过标签名(getElementsByTagName)
- 通过类名(getElementsByClassName)
- 通过选择器获取一个元素(querySelector)【不管是获取id还是class,只能获取到第一个元素】
- 通过选择器获取一组元素(querySelectorAll)
- 获取html的方法(document.documentElement)
- document.documentElement是专门获取html这个标签的
- 获取body的方法(document.body)
- document.body是专门获取body这个标签的。
数组的拷贝
//浅拷贝
1.使用=直接赋值
var newArr = arr;
2.使用slice()
var newArr = arr.slice();
3.使用concat()
var newArr = arr.concat();
//深拷贝
1.使用JSON.stringify和JSON.parse
var newArr = JSON.parse(JSON.stringify(arr));
2.深拷贝的一个通用方法
var deepCopy = function(obj) {
// 只拷贝对象
if (typeof obj !== 'object') return;
// 根据obj的类型判断是新建一个数组还是一个对象
var newObj = obj instanceof Array ? [] : {};
for (var key in obj) {
// 遍历obj,并且判断是obj的属性才拷贝
if (obj.hasOwnProperty(key)) {
// 判断属性值的类型,如果是对象递归调用深拷贝
newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
}
}
return newObj;
}
对象的深拷贝
const obj = {
data: 1,
un: undefined,
info: {
d: 2
},
fn: function() {
console.log('Function')
},
get c() {
return info.d
}
}
//浅拷贝
1.Object.assign
const ObjA = Object.assign({}, obj)
ObjA.data = 'a'
ObjA.info.d = 'b'
const ObjB = Object.assign({}, obj)
ObjB.data = 'c'
ObjB.info.d = 'd'
console.log(ObjA)
console.log(ObjB)
/*
==========输出==========
{ data: 'a', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
{ data: 'c', info: { d: 'd' }, un: undefined, fn: [Function: fn] }
*/
//我们会发现info.d 内容相等,说明Object.assign无法拷贝深层次内容,适用于浅层拷贝。
2.Object.create
const ObjA = Object.create(obj)
ObjA.data = 'a'
ObjA.info.d = 'b'
const ObjB = Object.create(obj)
ObjB.data = 'c'
ObjB.info.d = 'd'
console.log(ObjA)
console.log(ObjB)
console.log(ObjA.__proto__)
console.log(ObjB.__proto__)
/*
==========输出==========
{ data: 'a' }
{ data: 'c' }
{ data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
{ data: 1, info: { d: 'd' }, fn: [Function: fn], c: [Getter] }
*/
//Object.create 原型链继承,也可以达到内容浅层拷贝。
//----------------------------------深拷贝------------------------------------------
1.JSON.stringify & JSON.parse
const ObjA = JSON.parse(JSON.stringify(obj))
ObjA.data = 'a'
ObjA.info.d = 'b'
const ObjB = JSON.parse(JSON.stringify(obj))
ObjB.data = 'c'
ObjB.info.d = 'd'
console.log(ObjA)
console.log(ObjB)
/*
==========输出==========
{ data: 'a', info: { d: 'b' }, c: 2 }
{ data: 'c', info: { d: 'd' }, c: 2 }
*/
//我们将源对象转换为字符串,再转换为新对象虽然解决了深层次拷贝的问题,但我们会发现对象中的Function和undefined 无法拷贝,并且将c: [Getter] 直接转换成了键值对 c:2。
深拷贝函数
4.深拷贝函数
function checkType(any) {
return Object.prototype.toString.call(any).slice(8, -1)
}
function clone(any){
if(checkType(any) === 'Object') { // 拷贝对象
let o = {};
for(let key in any) {
o[key] = clone(any[key])
}
return o;
} else if(checkType(any) === 'Array') { // 拷贝数组
var arr = []
for(let i = 0,leng = any.length;i<leng;i++) {
arr[i] = clone(any[i])
}
return arr;
} else if(checkType(any) === 'Function') { // 拷贝函数
return new Function('return '+any.toString()).call(this)
} else if(checkType(any) === 'Date') { // 拷贝日期
return new Date(any.valueOf())
} else if(checkType(any) === 'RegExp') { // 拷贝正则
return new RegExp(any)
} else if(checkType(any) === 'Map') { // 拷贝Map 集合
let m = new Map()
any.forEach((v,k)=>{
m.set(k, clone(v))
})
return m
} else if(checkType(any) === 'Set') { // 拷贝Set 集合
let s = new Set()
for(let val of any.values()) {
s.add(clone(val))
}
return s
}
return any;
}
// 测试
var a = {
name: '张三',
skills: ['踢球', '跑步', '打羽毛球'],
age: 18,
love: {
name: '小红',
age: 16
},
map: new Map([['aaa', '123']]),
fn:function(a){
console.log(`我的名字叫${this.name}` + a)
},
set: new Set([1,2,3,4,5])
}
var newA = clone(a)
a.age = 100
a.love.age = 100
a.set.add('1123')
a.skills.push('计算机')
a.name = '小梅'
a.map.set('name', '小明')
console.log(a)
console.log(newA)
a.fn('a')
newA.fn('newA')
数组去重
1.new Set(array)//只适合纯数字
2.for 循环//适合数量少
var data = ['blue', 'red', 'green', 'blue'];
function UniqueData(data) {
for (var i = 0; i < data.length; i++) {
for (j = i + 1; j < data.length; j++) {
if (data[i] === data[j]) {
data.splice(j, 1);
}
}
}
return data;
}
UniqueData(data);
3.创建一个新数组,把原数组中的元素逐个添加到新数组中(判断新数组中是否已经包含原数组中的元素,如果没有,把原数组中的元素添加到新数组,如果已经存在,则不添加),因此就可以避免重复元素的产生了。
var data = ['blue', 'red', 'green', 'blue'];
function newData(data) {
var nData = new Array();
for (var i = 0; i < data.length; i++) {
if (nData.indexOf(data[i]) == -1) {
nData.push(data[i]);
}
}
return nData;
}
newData(data);
4.es6 推荐
let arr1 = [{ "name": 'a', "age": 18 }, { "name": 'b', "age": 19 }, { "name": 'c', "age": 20 }]
let arr2 = [{ "name": 'a', "age": 21 }, { "name": 'b', "age": 22 }, { "name": 'c', "age": 20 }, { "name": 'd', "age": 20 }]
let newarr = arr1.filter(x => !arr2.some(y => y.name == x.name && y.age == x.age))
二维数组转一维数组
//最简单的方法
let a=[1,[12,23],25,[65,87]]
a+='' //输出"1,12,23,25,65,87"
a.split(,)
//方法一
利用es5的arr.reduce(callback[, initialValue])实现
var arr1 = [[0, 1], [2, 3], [4, 5]];
var arr2 = arr1.reduce(function (a, b) { return a.concat(b)} );
// arr2 [0, 1, 2, 3, 4, 5]
//方法二:利用es6
优点: 多维数组也可以
比如:var arr = [[1,2],3,[[[4], 5]]]
var arr1 = [[0, 1], [2, 3], [4, 5]];
function flatten(arr) { return [].concat( ...arr.map(x => Array.isArray(x) ? flatten(x) : x) ) }
var arr2 = flatten(arr1); // arr2 [0, 1, 2, 3, 4, 5]
//方法三
//利用apply实现
var arr1 = [[0, 1], [2, 3], [4, 5]];
var arr2 = [].concat.apply([], arr1);
// arr2 [0, 1, 2, 3, 4, 5]
//方法四
通过将数组转变成字符串,利用str.split(',')实现。缺点是数组元素都变字符串了
var arr1 = [[0, 1], [2, 3], [4, 5]];
var arr2 = (arr1 + '').split(',');
var arr2 = arr.toString().split(',');
var arr2 = arr.join().split(',');
// arr2 ["0", "1", "2", "3", "4", "5"]
//方法五(补充)
利用 ES 的最新语法,Array.prototype.flat()。缺点是,有兼容性问题。优点是非常简单。
mdn 上是这么描述的:flat() 方法会递归到指定深度将所有子数组连接,并返回一个新数组。
语法:var newArray = arr.flat(depth),参数说明:depth,可选,指定嵌套数组中的结构深度,默认值为1。
//举例:
var arr1 = [1, 2, [3, 4]];
arr1.flat(); // [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(); // [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // [1, 2, 3, 4, 5, 6]
//Infinity展开所有嵌套数组
arr3.flat(Infinity); // [1, 2, 3, 4, 5, 6]
var arr4 = [1, 2, , 4, 5];
arr4.flat(); // [1, 2, 4, 5]
//特殊说明:flat()方法会移除数组中的空项。但undefined、null仍会保留。
var arr = [1, 2, undefined , 4, 5, null];
arr.flat(); // [1, 2, undefined , 4, 5, null]
math
Math.floor(x) // 返回小于x的最大整数
Math.floor(12.2) // 12
Math.floor(15 / 2) // 7
Math.ceil(x) // 返回大于x的最小整数
Math.ceil(12.2) // 13
Math.ceil(15 / 2) // 8
Math.round() 返回四舍五入后的整数
Math.round(12.2) // 12
Math.round(15 / 2) // 8
Math.random() 返回0到1之间的伪随机数.
Math.cos(x) 返回x的余弦值
Math.sin(x) 返回x的正弦值
\