Js使用记录2

2019.2.12 星期二

JS

  1. 主动触发滚动事件。
    el.dispatchEvent(new CustomEvent('scroll'))与双滚动+1和-1像素相比,感觉更糟糕(并且性能更高)
  2. crossorigin 值设置: 即使是无效的关键字和空字符串也会被当作 anonymous 关键字使用。
    但是对于跨域的资源 ,onerror事件通常会上报 “Script error”。
    而解决这个问题的一个办法之一就是在跨域资源的script标签中添加crossorigin属性

  3. ~~等价于Math.floor. ~~3.6=3(=~(~3.6)=~(-4+1)); ~3.6 = -4 (-(3+1))
    反码(~):二进制进行反码计算时。1变成0,0变成1。
    举例子~6,6的二进制是110在机器上补足32位在110之前补码0。那么反码为111…..001,此时的反码减去1得111…..111000,那么原反码减去相减的码得到0000….000111此时的十进制为-7
    那么加上原来减去的1得到-7+1就是~6了。(这个我也不是很懂。大牛们指正下)

  4. 字符串为空的true和false判断.注意 !判断

    1
    2
    3
    4
    5
    var s='',s1='  '; 
    !s==true// true
    !s1==false // true
    s==false // true
    s1==false // true
  5. js保留两位小数:tofixed 返回字符串,不能直接进行数字操作,需要转为数字

  6. 单例/字面量 定义时无法使用单例的方法
  7. 未定义的全局变量不可以直接使用,需要用window.varity,比如定义对象的属性值时
  8. int,long,float,double的 +, -, * 运算性能是一样的,除法运算比较慢,占用时间较多,要尽量避免除法。
    即:加,减,乘的运算时间与数据类型无关,所以可以随意使用更精确的float、double型,不影响程序速度。
  9. console.log(3+2 ? ‘1’ : ‘2’) //1
    console.log(3+2 && 4) // 4
    console.log(3+2) // 5
  10. 指定次数遍历
    数据循环mock.不需要 new Array(20).fill(1)

    1
    2
    3
    4
    5
    6
    7
    render: function (createElement) {
    return createElement('div',
    Array.apply(null, { length: 20 }).map(function () {
    return createElement('p', 'hi')
    })
    )
    }
  11. for in 循环顺序是不确定。
    使用for-in返回的属性因各个浏览器厂商遵循的标准不一致导致对象属性遍历的顺序有可能不是当初构建时的顺序。
    使用Object.keys 同for..in一样不能保证属性按对象原来的顺序输出。

    Chrome Opera 中使用 for-in 语句遍历对象的属性时,遍历出的属性顺序与对象定义时不同。

    简单归结成一句话就是:先遍历出整数属性(integer properties,按照升序),然后其他属性按照创建时候的顺序遍历出来。
    如果想要按照指定顺序遍历真么办,可以把key值调整为非整数属性.

    各浏览器 for-in 遍历对象属性的顺序差异

    1. 根据 ECMA-262(ECMAScript)第三版中描述,for-in 语句的属性遍历的顺序是由对象定义时属性的书写顺序决定的。
    2. 在现有最新的 ECMA-262(ECMAScript)第五版规范中,对 for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的。
    3. 新版本中的属性遍历顺序说明与早期版本不同,这将导致遵循 ECMA-262 第三版规范内容实现的 JavaScript 解析引擎(如IE6 IE7 IE8 Firefox Safari 浏览器的 JavaScript 解析引擎,它们完成时间早于 ECMA-262 第五版规范发布时间)在处理 for-in 语句时,与遵循第五版规范实现的解析引擎,对属性的遍历顺序存在不一致的问题。
  1. 在try catch finally 中return使用注意
    <!–
    注意:finally中最后不要有return语句,在编译器中会报警告。
    $_PS: 代码检查工具会报错
    js中try、catch、finally的执行规则

try catch缺点:
1.try catch耗性能
2.try catch捕获不到异步错误
3.try catch可能会导致报错点更模糊

有return的情况下try catch finally的执行顺序(最有说服力的总结)
try catch 语句中有return 的各类情况 –>
总结:
在正常情况(即程序正常执行try catch finally语句块,不会在语句中出现退出程序、线程终止等特殊情况)下,都会执行finally语句块,如果finally中有return,则程序会走finally中的return,如果没有,则先执行try或者catch中的return,将其存入临时栈中,执行完finally语句后才返回临时栈中的值。

  1. (0, function)()
    () 运算并返回内部表达式的结果。
    第一个写法里面包含一个逗号表达式”,”。 它会运算每个被逗号分开的表达式并返回最后一个表达式的结果。这种写法会先计算“0”,再计算匿名函数,并返回函数引用。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    (0, dog.run)();
    // 左边先用逗号操作符从左到右执行并取值,最终返回
    dog.run: function run() {
    console.log(this);
    console.log('I\'m running');
    }
    // 等价于如下,此时的 this 就是 全局对象 了
    (function run() {
    console.log(this);
    console.log('I\'m running');
    })();

为什么源码要用这种 (0, function)(param) 方式去绑定 this,而不是 function.call()/apply() 的形式呢?
那是因为这些源码中有时会修改 prototype ,将 call/apply 指向成自己的函数,甚至改变prototype 的指向,这样就会导致原型链上方法不可用,那就只好(0, function)(param ) 了。我理解这有点亡羊补牢的感觉。。。

  1. 对象数组去重
    js 删除两个数组中id相同的对象

    1
    2
    3
    4
    5
    6
    7
    let arr = res.data
    let arr1 = [...this.list]
    arr = arr.filter(item => {
    let arrlist = arr1.map(v => v.id)
    return !arrlist.includes(item.id)
    })
    this.data2 = arr
  2. 获取月份最后一天。比如2月最后一天, new Date(2019,2,0).getDate()

  1. Object.defineProperty。

    对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。
    configurable, enumerable; writable 默认是false.value,

    1. 如果定义存取描述符 返回的是空对象,对象属性依然可以读取
    2. get 里面不能再调用this.name, 会陷入死循环
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var obj = {name: 'helo'}
      Object.defineProperty(obj, 'name', {
      set(value) {
      this.name = value
      }
      });
      obj; // {}
      obj.name // hello
      // 数据描述
      Object.defineProperty({}, 'key2', {value: 22}) // {key2: 22}

    可以通过将值存储在另一个属性中解决。在 get 和 set 方法中,this 指向某个被访问和修改属性的对象。

  1. url 参数如果在js拼接要注意换行产生的空白

    1
    2
    3
    4
    5
    6
    7
    8
    // issue: 以下orderId参数会有空白
    gotoUrl({
    url: `../wuliumap/index?distance=${distance}&orderId=${orderId}
    &mapInfo=${encodeURIComponent(JSON.stringify(map))}`
    });
    // 这样ok。
    // }&dealState=${dealState
    // }&mapInfo=
  2. url 链接长度限制。
    实际过程,chrome 164645 也可以正常打开。

    微信小程序路径参数长度 214536 也正常加载了。

并非网络传言:Chrome URL最大长度限制为8182个字符。或小程序的128kb

但是并不排除某些机型会有问题。

  1. URI search 不同于 href.search
    home.html?coursewareid=44
    1
    2
    3
    4
    5
    6
    const params = (new URL(window.location)).searchParams;
    // const url = new URL(window.location);
    // const params = new URLSearchParams(url.search);

    const currCourseId = window.location.href.search('coursewareid') || '-'; // 32, 不知道什么问题
    // 可能用了字符串的search 方法找到索引,并不是值. href.search === String.prototype.search
  1. isNaN 区别于 Number.isNaN
    eslint 报isNaN 问题:[eslint] Unexpected use of 'isNaN'. (no-restricted-globals)
    ESLint Unexpected use of isNaN

    Why? The global isNaN coerces non-numbers to numbers, returning true for anything that coerces to NaN. If this behavior is desired, make it explicit.
    翻译:为什么? 全局isNaN强制非数字到数字,任何强迫NaN的事情 返回true。如果需要此行为,请进行此操作明确。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // bad
    isNaN('1.2'); // false
    isNaN('1.2.3'); // true
    // 相当于下面:Number转了一下,所以true。
    Number.isNaN(Number('1.2.3')); // true

    // good
    Number.isNaN('1.2'); // false
    Number.isNaN('1.2.3'); // false
  2. 存在一个非常好的 eval 替代方法:只需使用 window.Function。这有个例子方便你了解如何将eval()的使用转变为Function()。
    永远不要使用 eval!
    function looseJsonParse(obj){return Function('"use strict";return (' + obj + ')')();}

设备

  1. js 获取设备唯一id。OAID。

    别说浏览器,现在新版本的ios和Android10都关闭了获取IMEI的权限了
    <!– 获取OAID
    androidQ(api29)出来后,IMEI等等这些个设备唯一号都没法获取了,虽然androidID还能用但是这货可以重置甚至可能是个null,而甲方爸爸又偏偏指定要可靠的设备唯一号,只好硬着头皮在百度上搜,原来移动安全联盟(MSA)早已经预谋好了,研发出的SDK可以获取到叫做OAID的匿名设备唯一号,那么赶紧跟着这些大佬整齐划一。

    在AS的模拟器和雷电模拟器中,都没能获取到OAID。

  1. js获取wifi信息,比如ssid等 获取附近的SSID,这是由无线网卡的接收器来做的。这是属于系统资源
    本质上来说,浏览器是一个沙盒,是被隔离的,肯定不允许访问系统资源
    所以,很难实现,这是我的理解。
  2. 前端获取网络代理信息
  3. js获取网络信息。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // navigator.online
    window.addEventListener('online', function() {})

    //得到网络链接类型
    var type = navigator.connection.type;
    // 在第一次网络跳跃的时候得到下行最大比特率
    var max = navigator.connection.downlinkMax;
    // 网络链接改变时处理函数
    function changeHandler(e) {}

    // 注册网络链接改变事件
    navigator.connection.onchange = changeHandler;
    // 另一种注册方式
    navigator.connection.addEventListener('change', changeHandler);

dom

  1. removeEventListener 如果不指定handle 并不会删除所有事件监听。但是有些框架会默认实现。

浏览器

  1. 判断页面刷新

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    mounted(){
    if (window.performance.navigation.type == 1) {
    console.log("页面被刷新!")
    }else{
    console.log("首次被加载!")
    }
    }
    //还有一种方式就是通过检测路由的变化来判断是否页面被刷新
    router.beforeEach((to,from,next)=>{
    if (from.path === '/' && from.matched && from.matched.length === 0) {
    isFirstEnter = true; // 记录路由是否为刷新
    }
    next();
    })
  2. 刷新还是关闭 页面加载时只执行onload
    页面关闭时只执行onunload
    页面刷新时先执行onbeforeunload,然后onunload,最后onload。

数组

  1. 合并数组方式比较

    1. concat()
      合并多个数组,不影响原数组(会造成内存浪费),不能处理嵌套数组。
    2. 基于for循环 - push()
      没有concat的内存浪费,看上去土而且不好维护, 只能合并两个数组,会改变原数组,不能处理嵌套数组。
    3. apply a.push.apply(a, b);
      简洁高效,能实现多个数组合并, 会改变原数组, 并且能够实现深度嵌套。
    4. 更优美的push a.push(...b, ...c)
      多个数组合并, 会改变原数组, 效率比较高

    这与它们的运行机制有很大的关系:在合并数组的时候,.concat 创建了一个新的数组,而 .push 只是修改了第一个数组。这些额外的操作(将第一个数组的元素添加到返回的数组里)就是拖慢了 .concat 速度的关键。

  2. Array 和 new Array区别
    在jsx中直接写new Array() 会报错。因为要循环一个数字 10-var.length

    When Array is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments
      当数组作为函数调用而不是构造函数调用时,它会创建并初始化一个新的数组对象。因此当Array(…)和new Array(…)接收同样的参数时,它们是相同的。

    1) ES6中新增方法Array.of(), 将所有传入参数作为新建数组的元素,即使传入单个数值元素,Array.of(5) => [5];
    2) Array.apply(null, {length: 10}).map
    3) […Array(10)].map()

ES6

Module

  1. import的是时候出现undefined。
    原因:可能出现了循环引用。
    解决:解决引用:直接用数据,不使用import。

Promise

  1. promise.all 返回:只要都resolve或者只要有catch
  2. promise.finally 兼容
  3. async 实现不按顺序请求:paWeibo,imgsLoading 都没有实现
  4. async 没有finally

HTTP

ajax

  1. 可以获取请求接口的refer,即本页面。
    但是不能获取到来源页面,即当前html页面的refer。
  2. 可以支持设置或修改请求头。
    但是并不是所有请求头都可以修改的。

    Referer 请求头属于 Forbidden header,这种请求头无法通过程序来修改,浏览器客户端一般会禁止这种行为。以 Proxy- 和 Sec- 开头的请求头都属于 Fobidden header name,还包括以下这些请求头:

###

  1. ajax与302响 也就是说,重定向是由浏览器自动透明的完成的。所以服务器将302响应发给浏览器时,浏览器并不是直接处理ajax的回调,而是先执行302重定向。这就是上面例子中为什么获取不到xhr.status为302的值。

一个ajax请求的重定向大致流程是这样的:

ajax –> browser –> server –> 302 –> browser(redirect) –> server –> browser –> ajax callback
注意,上面ajax获取不到xhr的status是有一个前提:即,服务器为response设置了Location header。

因为,浏览器在发现Location的header时就会自动跳转到Location所指定的URL地址,类似于用js来进行重定向;不过这个重定向只有浏览器知道。
所以,在ajax接口返回302时,而没有设置Location的header时,这个xhr的status值还是能获取到的,下图是在浏览器控制台测试的结果:

  1. 预检请求缓存时效。
    mozilla -Access-Control-Max-Age

    这个因为浏览器会对预检请求进行缓存
    同时通过服务器端设置 Access-Control-Max-Age 字段来设置缓存时间
    那么当第一次请求该 URL 时会发出 OPTIONS 请求,浏览器会根据返回的 Access-Control-Max-Age 字段缓存该请求的 OPTIONS 预检请求的响应结果(具体缓存时间还取决于浏览器的支持的默认最大值,取两者最小值,一般为 10 分钟)。在缓存有效期内,该资源的请求(URL 和 header 字段都相同的情况下)不会再触发预检。(chrome 打开控制台可以看到,当服务器响应 Access-Control-Max-Age 时只有第一次请求会有预检,后面不会了。注意要开启缓存,去掉 disable cache 勾选。)

    在 Firefox 中,上限是24小时 (即 86400 秒)。
    在 Chromium v76 之前, 上限是 10 分钟(即 600 秒)。
    从 Chromium v76 开始,上限是 2 小时(即 7200 秒)。
    Chromium 同时规定了一个默认值 5 秒。
    如果值为 -1,表示禁用缓存,则每次请求前都需要使用 OPTIONS 预检请求。

<!-- 必须 url 是一样的, options 请求才会执行缓存效果, 而因为有 _t 的随机值存在,导致每次 get 的请求的 url 都是不一样,所以也就导致 options 缓存失效了。 -->
  1. content-type差别: application/javascript,application/x-javascript,text/javascript

    text/javascript is obsolete, and application/x-javascript was experimental (hence the x- prefix) for a transitional period until application/javascript could be standardised.
    Difference between application/x-javascript and text/javascript content types
    Which MIME type suits JavaScript?

    [在提供JavaScript文件时,使用application / javascript还是application / x-javascript会更好(https://cloud.tencent.com/developer/ask/52563)
    application/x-javascript 和 text/javascript 内容类型之间的区别

knowledge is no pay,reward is kindness
0%