一、数组解决

1. 数组去重

1. 纯数组去重(6种办法)

class ArrayToHeavy {      // new Set去重      newSetHeavy(arr) {        return Array.from(new Set(arr))      }      // .indexOf或lastIndexOf去重      indexHeavy(arr) {        let newArr = [];        arr.forEach((val, index) => {          newArr.indexOf(val) === -1 ? newArr.push(val) : '';        });        return newArr      }      // 通过filter过滤返回一个新数组在原数组中比照用indexof去重      filterHeavy(arr) {        return arr.filter((item, index, self) => {          return self.indexOf(item) === index; //比拟数组中每一项是否为其(indexof)首次查找的索引值(index)        })      }      // 通过splice扭转原数组去重      spliceHeavy(arr) {        let len = arr.length;        for (let i = 0; i < len; i++) {          for (let j = i + 1; j < len; j++) {            if (arr[i] == arr[j]) {              arr.splice(j, 1);              len--;              j--            }          }        }      }      /* 相邻元素去重       这种办法首先调用了数组的排序办法sort(),而后依据排序后的后果进行遍历及相邻元素比对,       如果相等则跳过改元素,直到遍历完结 */      uniqueHeavy(arr) {        if (!Array.isArray(arr)) {          console.log('type error!')          return        }        arr = arr.sort()        let res = []        for (let i = 0; i < arr.length; i++) {          if (arr[i] !== arr[i - 1]) {            res.push(arr[i])          }        }        return res      }      /* 利用对象属性去重        创立空对象,遍历数组,将数组中的值设为对象的属性,并给该属性赋初始值1,        每呈现一次,对应的属性值减少1,这样,属性值对应的就是该元素呈现的次数了 */     ObjHeavy(arr) {      if (!Array.isArray(arr)) {        console.log('type error!')        return      }      let res = [],        obj = {}      for (let i = 0; i < arr.length; i++) {        if (!obj[arr[i]]) {          res.push(arr[i])          obj[arr[i]] = 1        } else {          obj[arr[i]]++        }      }      return res    }    }    const ArrayToHeavy_handle = new ArrayToHeavy()    console.log(ArrayToHeavy_handle.newSetHeavy([1, 1])) // [1]

2. 对象数组去重

1. 去重雷同id的对象
let person = [{ id: 0, name: "A" },{ id: 0, name: "b" }];let obj = {};let peon = person.reduce((cur, next) => {  obj[next.id] ? "" : (obj[next.id] = true && cur.push(next));  return cur;}, []); //设置cur默认类型为数组,并且初始值为空的数组peon // [{ id: 0, name: "A" }]

2. 数组排序10种实用办法

{1} 冒泡排序

  • 解释:冒泡排序算法就是顺次比拟大小,小的的大的进行地位上的替换。
  • 实现原理:
    当i=0的时候,外面的循环残缺执行,从j=0执行到j=6,这也就是第一遍排序,后果是将最大的数排到了最初,这一遍循环完结后的后果应该是[8,34,21,53,12,95

当i=1的时候,外面的循环再次残缺执行,因为最大的数曾经在最初了,没有必要去比拟数组的最初两项,这也是j<arr.length-1-i的奇妙之处,后果是[8,34,21,12,53,95]
说到这里,法则就分明了,每次将剩下数组外面最大的一个数排到最初面,当第一个循环执行到最初的时候,也就是i=6,此时,j=0,只须要比拟数组的第一和第二项,比拟结束,返回。

let arr=[8,95,34,21,53,12]; function sortarr(arr){  for(i=0;i<arr.length-1;i++){   for(j=0;j<arr.length-1-i;j++){    if(arr[j]>arr[j+1]){     var temp=arr[j];     arr[j]=arr[j+1];     arr[j+1]=temp;    }   }  }  return arr; } sortarr(arr); // [8,12,21,34,53,95]

(2) 抉择排序

  • 解释:顺次找到残余元素最小值,搁置排好序的开端(第一个放在结尾)
    在工夫复杂度上体现最稳固的排序算法之一,因为无论什么数据进去都是O(n²)的工夫复杂度,所以用到它的时候,数据规模越小越好。惟一的益处可能就是不占用额定的内存空间

    function selectionSort(arr) {var len = arr.length;var minIndex, temp;for (var i = 0; i < len - 1; i++) {    minIndex = i;    for (var j = i + 1; j < len; j++) {        if (arr[j] < arr[minIndex]) {     //寻找最小的数            minIndex = j;                 //将最小数的索引保留        }    }    temp = arr[i];    arr[i] = arr[minIndex];    arr[minIndex] = temp;}return arr;}

    3. 数组拷贝

    (1) [].concat.apply([], 被拷贝的数组) 适宜解决一维数组

let a = [1,2];let b = [].concat.apply([], a);b[0] = 0;a // => [1, 2]b // => [0, 2]

4.解决二维数组

(1) 将间断的二维数组中的对应索引项合并为一个数组,返回合并后的二维数组

输出:var data = [[2001, 10, 20],[2002, 30 ,40],[2003, 50 ,60]]输入:[[2001, 2002, 2003],[10, 30, 50],[20, 40, 60]]实现:    var getBarData = [];    data[0].map(item => {      getBarData.push([])    });    data.forEach((item, inx) => {      for(var i = 0; i < data[0].length; i++) {        getBarData[i].push(item[i])      }    })

5. 按指定条件查找数组中的元素

(1) 查找数组最大值

 输出:   let a = [1,2,3,4] 输入: 4
1. 利用Math办法通过apply 将数组元素一个一个拆分开来,而后在传递到Math.max()办法中Math.max.apply(null, a)2. Math.max(...a)3. 利用sort办法    let resultArr = a.sort(function(a, b) {      return b - a;     });     resultArr[0] // 5

6. 按指定条件过滤数组

(1) 过滤数组中值为 false 的值

输出: let a = [0,0,false,null,3]输入: [3]
let b = a.filter(Boolean) // [3]

7. 类数组转为数组

(1) [].slice.call(obj) Array.prototype.slice.call(obj) Array.prototype.concat.apply([],obj)

[].slice.call({length:2,0:1,1:2}) // [1 ,2]Array.prototype.concat.apply([],{length:1,0:1}) // [1]

(2) Array.from(cArr) [...obj]

Array.from({length:1,0:1}) // [1]

8.扁平化数组

输出: var arr = [[[1,2,3],[[4,5,6]]]]输入: [1,2,3,4,5,6]

(1) reduce递归法

 var flatten = (arr) => {          return arr.reduce((pre, next) => {              return pre.concat(Array.isArray(next) ? flatten(next) : next);          }, [])         }        flatten(arr) // [1,2,3,4,5,6]

二、对象解决

1. 将对象转为数组

  • 利用Object.keys()

    const obj = {     "sex_wxx": "性别",     "income_wxx": "支出",     "age_wxx": "年龄" }; let arr = []; Object.keys(obj).forEach(v => {     let o = {};     o[v] = obj[v];     arr.push(o) })console.log(arr) // [{sex_wxx: '性别'}, {income_wxx: '支出'},{age_wxx: '年龄'}]
  • 利用Object.entries()
Object.entries(obj).forEach(item => { let o = {}o[item[0]] = item[1]arr.push(o)})
  • Object.keys()和map()联合
Object.keys(obj).map(v => { return v = {[v]: obj[v]} })

2. 递归对象获取value

var obj = { a:{w:1,y:2,x:3},b:{s:4,j:5,x:6},c:{car:7,cat:8,mao:9}}function f(s){for(var i in s){if(typeof s[i]=="object"){f(s[i])}else{   console.log(s[i]);  }}}f(obj) // 1,2,3,4,5,6,7,8,9

3. 判断两个对象是否相等

Object.entries({name:1}).toString() === Object.entries({name:1}).toString() // true

4. 从一个对象条件匹配另一个对象

用过滤(filter)判断(every)每一项是否符合条件

let obj = {name:  'ops'}let arr = [{name: 'q'}, {name: 'ops', kl: 'oop'}]var _key= Object.keys(obj)arr.filter(item=>_key.every(k=>obj[k]===item[k])) // {name: 'ops', kl: 'oop'}

5. 对象转为url参数拼接

输出:

{a:1,b:2}

输入:

a=1&b=2
function obj2strUrl (obj) {    let str="";    for (let key in obj) {      str = `${str}${key}=${obj[key]}&`    };    str = str.substring(0, str.length-1);    return str;}

反转:拼接的url参数转为对象

/** * @param {string} url * @returns {Object} */function param2Obj(url) {  const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')  if (!search) {    return {}  }  const obj = {}  const searchArr = search.split('&')  searchArr.forEach(v => {    const index = v.indexOf('=')    if (index !== -1) {      const name = v.substring(0, index)      const val = v.substring(index + 1, v.length)      obj[name] = val    }  })  return obj}

三、字符串解决

1. 将被字符串包裹的对象转为js对象

输出 '{name: qwer, id: 1, ops: poi}',=> 输入 {name: 'qwer', id: '1', ops: 'poi'}

function strToObj(str) {    let arr = str.replace(/{|}|\s*/g, '').split(','),        obj = {}    arr.forEach(val => {        let i = val.indexOf(':')        obj[val.substr(0, i)] = val.substr(i + 1);});return obj}console.log(strToObj('{name: qwer, id: 1, ops: poi}')) => {name: 'qwer', id: '1', ops: 'poi'}

2. 格式化string/number类型的日期

let date = '20220408000009';function f(str, type) {let i = 0,_type = type || 'xxxx-xx-xx xx:xx:xx'return _type.replace(/x/g, () => str[i++])}f(date)

3. 计算字符串宽度(px)

// 1. 准确计算function computedTextWidth (text) {    var canvas = document.createElement('canvas');     canvas.id = 'computedTextWidth';     canvas.style.cssText = 'visibility:hidden;position: absolute;left: -999em;top:-999em;';     document.body.appendChild(canvas);    var context = canvas.getContext('2d');    context.font = '12px';    context.fillText(text, 0, 0);    return context.measureText(text).width;}computedTextWidth('33333333') // 100// 2. 误差计算(差值为1/4)computedTextWidth(text, fontSize = 14) {  let span = document.getElementById('computedTextWidth');  if (!span) {    span = document.createElement('span');    span.id = 'computedTextWidth';    span.style.cssText = 'visibility:hidden;position: absolute;left: -999em;top:-999em;';    document.body.appendChild(span);  }  span.style.fontSize = `${fontSize}px`;  span.innerHTML = text;  return span.offsetWidth;};

4. 提取字符串中的数字

(1) match办法
var str = '123AAAA098'var numArr = str.match(/\d+/g)    numArr // => ["123", "098"]
(2) replace办法
var s ="4500元,6,700";var num= s.replace(/[^0-9]/ig,"");num // 45006700

5. 提取字符串中的指定值(度量值)

let str = '申请量 3 件,总量 3,541,98234,4.5,90% ,4.5%件。';str.match(/\d+(.\d+\%)|\d+(,\d+)|\d+(\.\d+)|\d+\%|\d+/img);str // ['3', '3,541', '98234', '4.5', '90%', '4.5%']

四、日期工夫类

1. 依据开始工夫 + 日/月/年数 计算截止日期

(1) 开始日期+天数=截止日期

export function getEndDay(dateTemp, days) {  dateTemp = dateTemp.split("-")  var nDate = new Date(dateTemp[1] + "-" + dateTemp[2] + "-" + dateTemp[0]) // 格式化工夫  var millSeconds = Math.abs(nDate) + days * 24 * 60 * 60 * 1000  var rDate = new Date(millSeconds)  var year = rDate.getFullYear()  var month = rDate.getMonth() + 1  if (month < 10) month = "0" + month  var date = rDate.getDate()  if (date < 10) date = "0" + date  return year + "-" + month + "-" + date}应用: getEndDay('年-月-日', '天数')例: getEndDay('2021-11-11', '1')  =>  '2021-11-12'

(2) 开始日期+月数=截止日期

 export function getEndMonth(dtstr, n) {     var s = dtstr.split("-")     var yy = parseInt(s[0])     var mm = parseInt(s[1])     var dd = parseInt(s[2])     var dt = new Date(yy, mm, dd)          var num=dt.getMonth() + parseInt(n)     if(num/12>1){        yy+=Math.floor(num/12)        mm=num%12     }else{         mm+=parseInt(n)     }     return yy + "-" + mm  + "-" + dd } 应用: getEndMonth('年-月-日', '月数') 例: getEndMonth('2021-11-11', '1')  =>  '2021-12-11'

(3)开始日期+年数=截止日期

export function getEndYear(date, years) {  var now = new Date(date);  var intYear = now.getFullYear() + parseInt(years);  var intMonth = now.getMonth() + 1; //失常的月份,  var intDay = now.getDate() - 1; //日期-1  if (intDay == 0) {  intMonth--; //缩小一个月  if (intMonth == 0) {  intYear--; //0:缩小一年  intMonth = 12;  intDay = 31;  }  else if (intMonth == 4 || intMonth == 6 || intMonth == 9 || intMonth == 11) {  intDay = 30; //4,6,9,11:30天  }  else if (intMonth == 2) {  intDay = 28; //2:28/29  if (intYear % 4 == 0) {  intDay = 29;  }  } else {  intDay = 31; //1,3,5,7,8,10,12 :31天  }  }  var strMonth = (intMonth) < 10 ? "0" + (intMonth).toString() : (intMonth).toString();  var strDay = (intDay) < 10 ? "0" + (intDay).toString() : (intDay).toString();  var strEndDate = intYear + "-" + strMonth + "-" + strDay;  return strEndDate;  }  应用: getEndYear('年-月-日', '月数')   例: getEndYear('2021-11-11', '1') => '2022-12-11'

2. 获取指定日期工夫

export function timeStremHandle() {  let now = new Date() //以后日期  let nowDayOfWeek = now.getDay() //明天本周的第几天  let nowDay = now.getDate() //以后日  let nowMonth = now.getMonth() //以后月  let nowYear = now.getYear() //以后年  nowYear += (nowYear < 2000) ? 1900 : 0  let lastMonthDate = new Date() //上月日期  lastMonthDate.setDate(1)  lastMonthDate.setMonth(lastMonthDate.getMonth() - 1)  let lastYear = lastMonthDate.getYear()  let lastMonth = lastMonthDate.getMonth()  return {// 格式化日期:yyyy-MM-dd    formatDate(date) {      var myyear = date.getFullYear()      var mymonth = date.getMonth() + 1      var myweekday = date.getDate()      if (mymonth < 10) {        mymonth = "0" + mymonth      }      if (myweekday < 10) {        myweekday = "0" + myweekday      }      return (myyear + "-" + mymonth + "-" + myweekday)    },        // 获取间断数字年月日    getNumDate(){      function formatNumber(n) {        n = n.toString()       return n[1] ? n : '0' + n        }      function formatDay (date) {       var year = date.getFullYear()       var month = date.getMonth() + 1       var day = date.getDate()       return [year, month, day].map(formatNumber).join('') + ''     }             调用: formatDay(new Date()) // '20220923'    },//取得某月的天数    getMonthDays(myMonth) {      var monthStartDate = new Date(nowYear, myMonth, 1)      var monthEndDate = new Date(nowYear, myMonth + 1, 1)      var days = (monthEndDate - monthStartDate) / (1000 * 60 * 60 * 24)      return days    },//取得本季度的开始月份    getQuarterStartMonth() {      var quarterStartMonth = 0      if (nowMonth < 3) {        quarterStartMonth = 0      }      if (2 < nowMonth && nowMonth < 6) {        quarterStartMonth = 3      }      if (5 < nowMonth && nowMonth < 9) {        quarterStartMonth = 6      }      if (nowMonth > 8) {        quarterStartMonth = 9      }      return quarterStartMonth    },//取得本周的开始日期    getWeekStartDate() {      var weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek)      return formatDate(weekStartDate)    },//取得本周的进行日期    getWeekEndDate() {      var weekEndDate = new Date(nowYear, nowMonth, nowDay + (6 - nowDayOfWeek))      return formatDate(weekEndDate)    },//取得本月的开始日期    getMonthStartDate() {      var monthStartDate = new Date(nowYear, nowMonth, 1)      return formatDate(monthStartDate)    },//取得本月的进行日期    getMonthEndDate() {      var monthEndDate = new Date(nowYear, nowMonth, getMonthDays(nowMonth))      return formatDate(monthEndDate)    },//取得上月开始日期    getLastMonthStartDate() {      var lastMonthStartDate = new Date(nowYear, lastMonth, 1)      return formatDate(lastMonthStartDate)    },//取得上月进行日期    getLastMonthEndDate() {      var lastMonthEndDate = new Date(nowYear, lastMonth, getMonthDays(lastMonth))      return formatDate(lastMonthEndDate)    },//取得本季度的开始日期    getQuarterStartDate() {      var quarterStartDate = new Date(nowYear, getQuarterStartMonth(), 1)      return formatDate(quarterStartDate)    },//取得本季度的截止日期    getQuarterEndDate() {      var quarterEndMonth = getQuarterStartMonth() + 2      var quarterStartDate = new Date(nowYear, quarterEndMonth, getMonthDays(quarterEndMonth))      return formatDate(quarterStartDate)    },    //日期减    DateDiff(sDate1, sDate2) {      var aDate, oDate1, oDate2, iDays      aDate = sDate1.split("-")      oDate1 = new Date(aDate[0], aDate[1] - 1, aDate[2])      aDate = sDate2.split("-")      oDate2 = new Date(aDate[0], aDate[1] - 1, aDate[2])      iDays = parseInt(Math.abs(oDate1 - oDate2) / 1000 / 60 / 60 / 24)      if ((oDate1 - oDate2) < 0) {        return -iDays      }      return iDays    },// 最近一个月年月日 latelyTimeStrem() {  var strem = new Date(now)  strem.setDate(now.getDate() - 30)  return {    startDay: this.formatDate(new Date(nowYear, nowMonth, nowDay -30)),    nowDay: this.formatDate(new Date(nowYear, nowMonth, nowDay))  } }  }}

3. 获取以后工夫戳

export function getTime(type) {    if (type === 'start') {      return new Date().getTime() - 3600 * 1000 * 24 * 90    } else {      return new Date(new Date().toDateString())    }  }

4. 将工夫戳转为 {y}-{m}-{d} {h}:{i}:{s}

/** * @param {(Object|string|number)} time * @param {string} cFormat * @returns {string | null} * @description 工夫戳转为年月日时分秒 * @example parseTime(1656577144101)  2022-06-30 16:19:04;  *          获取星期几:parseTime(1656577144101, '{y}-{m}-{d} {h}:{i}:{s}{a}'); 2022-06-30 16:19:04四 */export function parseTime(time, cFormat) {  if (arguments.length === 0 || !time) {    return null  }  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'  let date  if (typeof time === 'object') {    date = time  } else {    if ((typeof time === 'string')) {      if ((/^[0-9]+$/.test(time))) {        time = parseInt(time)      } else {        // https://stackoverflow.com/questions/4310953/invalid-date-in-safari        time = time.replace(new RegExp(/-/gm), '/')      }    }    if ((typeof time === 'number') && (time.toString().length === 10)) {      time = time * 1000    }    date = new Date(time)  }  const formatObj = {    y: date.getFullYear(),    m: date.getMonth() + 1,    d: date.getDate(),    h: date.getHours(),    i: date.getMinutes(),    s: date.getSeconds(),    a: date.getDay()  }  const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {    const value = formatObj[key]    // Note: getDay() returns 0 on Sunday    if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }    return value.toString().padStart(2, '0')  })  return time_str}

5. 获取零碎时分秒

  export function getSystemTime() {    let timer = null    setInterval(function () {      let time = new Date()      let hour = checkTime(time.getHours())      let minite = checkTime(time.getMinutes())      let second = checkTime(time.getSeconds())      function checkTime(i) {        if (i < 10) return "0" + i        return i      }      timer = hour + ":" + minite + ":" + second      return timer    }, 1000)  }

6.计算两个日期之间的距离

const dayDif = (date1, date2) =>Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000)dayDif(new Date("2022-11-3"), new Date("2022-2-1"))  // 275

7. 查找日期位于一年中的第几天

const dayOfYear = (date) => Math.floor((date - new Date(date.getFullYear(), 0, 0)) / 1000 / 60 / 60 / 24);dayOfYear(new Date());   // 311

五、 屏蔽浏览器控制台

1.写一个回调函数,让页面进行死循环

!function(){        var _0x1cbb = ["tor", "struc", "call", "ger", "con", "bug", "de", "apply"];        setInterval(check, 2e3);        function check() {            function doCheck(_0x1834ff) {                if (('' + _0x1834ff / _0x1834ff)['length'] !== 0x1 || _0x1834ff % 0x14 === 0x0) {                    (function() {return !![]}[                        _0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]                    ](                        _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]                    )[_0x1cbb[0x2]]());                } else {                    (function() {return ![]}[                        _0x1cbb[0x4] + _0x1cbb[0x1] + _0x1cbb[0x0]                    ](                        _0x1cbb[0x6] + _0x1cbb[0x5] + _0x1cbb[0x3]                    )[_0x1cbb[0x7]]());                }                doCheck(++_0x1834ff);            }            try {                doCheck(0)            } catch(err) { }        };      }();

六、加密算法

SHA加密

解释: SHA-1是一种数据加密算法,该算法的思维是接管一段明文,而后以一种不可逆的形式将它转换成一段(通常更小)密文,也能够简略的了解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输入序列即散列值(也称为信息摘要或信息认证代码)的过程。

function encodeUTF8 (s) {        var i, r = [], c, x        for (i = 0; i < s.length; i++)        if ((c = s.charCodeAt(i)) < 0x80) r.push(c)        else if (c < 0x800) r.push(0xC0 + (c >> 6 & 0x1F), 0x80 + (c & 0x3F))        else {            if ((x = c ^ 0xD800) >> 10 == 0) //对四字节UTF-16转换为Unicode            c = (x << 10) + (s.charCodeAt(++i) ^ 0xDC00) + 0x10000,                r.push(0xF0 + (c >> 18 & 0x7), 0x80 + (c >> 12 & 0x3F))            else r.push(0xE0 + (c >> 12 & 0xF))            r.push(0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F))        }        return r    }function sha (s) { // sh1 编码          var data = new Uint8Array(encodeUTF8(s))          var i, j, t          var l = ((data.length + 8) >>> 6 << 4) + 16, s = new Uint8Array(l << 2)          s.set(new Uint8Array(data.buffer)), s = new Uint32Array(s.buffer)          for (t = new DataView(s.buffer), i = 0; i < l; i++)s[i] = t.getUint32(i << 2)          s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8)          s[l - 1] = data.length << 3          var w = [], f = [            function () { return m[1] & m[2] | ~m[1] & m[3] },            function () { return m[1] ^ m[2] ^ m[3] },            function () { return m[1] & m[2] | m[1] & m[3] | m[2] & m[3] },            function () { return m[1] ^ m[2] ^ m[3] }          ], rol = function (n, c) { return n << c | n >>> (32 - c) },            k = [1518500249, 1859775393, -1894007588, -899497514],            m = [1732584193, -271733879, null, null, -1009589776]          m[2] = ~m[0], m[3] = ~m[1]          for (i = 0; i < s.length; i += 16) {            var o = m.slice(0)            for (j = 0; j < 80; j++)              w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1),                t = rol(m[0], 5) + f[j / 20 | 0]() + m[4] + w[j] + k[j / 20 | 0] | 0,                m[1] = rol(m[1], 30), m.pop(), m.unshift(t)            for (j = 0; j < 5; j++)m[j] = m[j] + o[j] | 0          }          t = new DataView(new Uint32Array(m).buffer)          for (var i = 0; i < 5; i++)m[i] = t.getUint32(i << 2)                  var hex = Array.prototype.map.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {            return (e < 16 ? "0" : "") + e.toString(16)          }).join("")          return hex    }sha(123456); // 7c4a8d09ca3762af61e59520943dc26494f8941b