MyFunction

107 阅读6分钟

日期

//获取日期之间的日期数组
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.stringifyJSON.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(,)

//方法一
利用es5arr.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()  返回01之间的伪随机数.

Math.cos(x) 返回x的余弦值

Math.sin(x) 返回x的正弦值

\