小零碎

168 阅读5分钟

1 判断当前脚本运行在何种环境(browser / node)

// 通过判断 Global 对象是否为 window,如果不是则代表没有运行在浏览器中
this === window ? 'browser' : 'node'

2 什么是 Polyfill

Polyfill 指的是用于实现浏览器不支持的原生 API(写补丁)

3 使用 js 获取文件的扩展名

let fileExtension = fileName.substring(fileName.lastIndexOf('.') + 1);
}

4 Object.is(), "==" 和 "==="

  • '==':会在比较时进行类型转换
  • '===':判断严格,不进行隐式类型转换,类型不同也会返回 false
  • object.is(val1,val2):在三等号判断的基础上特别处理 NaN 和 NaN 相同, +0 和 -0 不相同

5 Unicode 和 UTF-8 的区别

Unicode 是一种字符集合,现在可容纳 100 多万个字符。每个字符对应一个不同的 Unicode 编码,它只规定了符号的二进制代码,却没有规定这个二进制代码在计算机中如何编码传输。

UTF-8 是一种对 Unicode 的编码方式,它是一种变长的编码方式,可以用 1~4 个字节来表示一个字符。

6 escape、encodeURI、encodeURIComponent

  • encodeURI:对整个 URI 包括非法字符但不包括对 URI 有特殊意义的字符

  • encodeURIComponent:对 URI 的组成部分包括特殊字符进行转义
  • escape:与 encodeURI 作用相同,但是 escape 是直接在字符的 unicode 编码前加上 %u,而 encodeURI 首先会将字符转换为 UTF-8 的格式,再在每个字节前加上 %。

7 防抖和节流

  1. 函数防抖:在事件被触发的 n 秒后再执行回调。如果在 n 秒内,事件再次被触发,则重新计时。
function debounce (fn, wait) {
    let timer = null;
    
    return function () {
        let context = this;
        let args = arguments;
        
        if(timer) {
            clearTimeout(timer);
            timer = null;
        }
        
        timer = setTimeout(function () {
            fn.apply(context, args)
        }, wait)
    }
}

const fn = function () {
    console.log('debounce...')
}

// 1500ms 后触发第一次,此后每 1000ms 触发一次
setInterval(debounce(fn, 500), 1000)

// 不会触发
setInterval(debounce(fn, 1000), 500)
  1. 函数节流:规定一个单位时间,在单位时间内只能有一次触发事件的回调函数。即使在单位时间内事件被触发多次也只有一次执行回调。
 * 节流
 * @param {function} func function
 * @param {number} limit limit
 * @returns {function} func
 */
const throttle = (func, limit) => {
  let lastFunc;
  let lastRan;

  return function() {
    const context = this;
    const args = arguments;

    if (!lastRan) {
      // 记录第一次运行的时间
      func.apply(context, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function() {
        if (Date.now() - lastRan >= limit) {
          func.apply(context, args);
          lastRan = Date.now()
        }
      }, limit - (Date.now() - lastRan))
    }
  }
};

8 手写深浅拷贝

function shallowCpoy(object) {
    if(!object || typeOf object !== 'object') return;
    
    let newObject = Array.isArray(object) ? [] : {};
    for(let key in object) {
        if(object.hasOwnProperty(key)) {
            newObj[key] = object[key];
        }
    }
    
    return newObject;
}

function deepCopy(object) {
    if(!object || typeOf object !== 'object') return;
    
    let newObject = Array.isArray(object) ? [] : {};
    for(let key in object) {
        if(object.hasOwnProperty(key)) {
            if(typeOf object[key] === 'object') {
                newObj[key] = deepCopy(object[key])
            } else {
                newObj[key] = object[key];
            }
        }
    }
    
    return newObject;
}

9 手写 call、apply 和 bind 函数

todo

10 toPrecision、toFixed、Math.round

  • toPrecision(precision):四舍五入到指定的精度
  • toFixed:对小数点后指定位数取整
  • Math.round():四舍五入到一个整数

11 link 和 @import 的区别

  1. link 是 HTML 标签,@import 是 css 提供的
  2. link 引入的样式页面加载时同时加载,@import 引入的样式需等页面加载完成后再在家
  3. link 没有兼容性问题,@import 不兼容 ie5 以下
  4. link 可以通过 js 操作 DOM 动态引入样式表改变样式,而 @import 不可以

12 圣杯布局和双飞翼布局

作用:圣杯布局和双飞翼布局解决的问题是一样的,就是两边顶宽,中间自适应的三栏布局,中间栏要在放在文档流前面以优先渲染。

区别:圣杯布局,为了中间div内容不被遮挡,将中间div设置了左右padding-left和padding-right后,将左右两个div用相对布局position: relative并分别配合right和left属性,以便左右两栏div移动后不遮挡中间div。双飞翼布局,为了中间div内容不被遮挡,直接在中间div内部创建子div用于放置内容,在该子div里用margin-left和margin-right为左右两栏div留出位置。

// 圣杯布局
<body>
<div id="hd">header</div>
<div id="bd">
  <div id="middle">middle</div>
  <div id="left">left</div>
  <div id="right">right</div>
</div>
<div id="footer">footer</div>
</body>

<style>
#hd{
    height:50px;
    background: #666;
    text-align: center;
}
#bd{
    /*左右栏通过添加负的margin放到正确的位置了,此段代码是为了摆正中间栏的位置*/
    padding:0 200px 0 180px;
    height:100px;
}
#middle{
    float:left;
    width:100%;/*左栏上去到第一行*/
    height:100px;
    background:blue;
}
#left{
    float:left;
    width:180px;
    height:100px;
    margin-left:-100%;
    background:#0c9;
    /*中间栏的位置摆正之后,左栏的位置也相应右移,通过相对定位的left恢复到正确位置*/
    position:relative;
    left:-180px;
}
#right{
    float:left;
    width:200px;
    height:100px;
    margin-left:-200px;
    background:#0c9;
    /*中间栏的位置摆正之后,右栏的位置也相应左移,通过相对定位的right恢复到正确位置*/
    position:relative;
    right:-200px;
}
#footer{
    height:50px;
    background: #666;
    text-align: center;
}
</style>
// 双飞翼布局
<body>
<div id="hd">header</div> 
  <div id="middle">
    <div id="inside">middle</div>
  </div>
  <div id="left">left</div>
  <div id="right">right</div>
  <div id="footer">footer</div>
</body>

<style>
#hd{
    height:50px;
    background: #666;
    text-align: center;
}
#middle{
    float:left;
    width:100%;/*左栏上去到第一行*/     
    height:100px;
    background:blue;
}
#left{
    float:left;
    width:180px;
    height:100px;
    margin-left:-100%;
    background:#0c9;
}
#right{
    float:left;
    width:200px;
    height:100px;
    margin-left:-200px;
    background:#0c9;
}

/*给内部 div 添加 margin,把内容放到中间栏,其实整个背景还是100%*/ 
#inside{
    margin:0 200px 0 180px;
    height:100px;
}
#footer{  
   clear:both; /*清除浮动*/  
   height:50px;     
   background: #666;    
   text-align: center; 
}
</style>

负 margin 可参考:segmentfault.com/a/119000001…

13 js 生成随机数

  • ceil:向上取整
  • floor、parseInt:向下取整
  • round:四舍五入
  • random:返回0~1之间的随机数,包含0不包含1

生成随机整数: Math.floor(Math.random() * (max-min)) + min