js常见函数总结(一)

[TOC]

编写一个方法,求一个字符串的长度

    function getbytes(str){
        var len = str.length;
        var bytes = len;
        for (var i=0;i<len;i++){
            if(str.charCodeAt(i)>255)bytes++
        }
        return bytes;
    }
复制代码

如何统计字符串“aaaabbbccccddfgh”

var str = 'aaaabbbccccddfgh';
dealStr(str);
function dealStr(str) {
    var obj = {};
    for(var i=0;i<str.length;i++){
        var v = str.charAt(i);
        if(obj[v] && obj[v].value === v){
            ++obj[v].count
        }else{
            obj[v] = {
                count:1,
                value:v
            }
        }
    }
    return obj;
}
var obj = dealStr(str);
for(key in obj){
    console.log(obj[key].value + '=' +obj[key].count)
}
复制代码

深拷贝

    //deepClone函数
    function deepClone(obj){
        let objClone = Array.isArray(obj)?[]:{};
        if(obj && typeof obj === 'object'){
            for(key in obj){
                if(obj.hasOwnProperty(key)){
                    //判断obj子元素是否为对象,如果是,递归复制
                    if(obj[key] && typeof obj[key] == 'object'){
                        objClone[key] = deepClone(obj[key]);
                    }else{
                        objClone[key] = obj[key];
                    }
                }
            }
        }
    }
    
复制代码

写一个function,清除字符串前后的空格(兼容所有浏览器)

function trim(str) {
    if(str && typeof str == 'string'){
        return str.replace(/^\s+|\s+$/g,"");
    }
}
复制代码

请说出阻止事件冒泡的方法

function stopBubble(e) {
    var evt = e||window.event;
    evt.stopPropagation ? evt.stopPropagation() : (evt.cancelBubble = true);
}
复制代码

以下两个函数会返回相同的结果吗?为什么

function foo1() {
    return {
        bar:'hello'
    }
}
function foo2() {
    return
    {
        bar:'hello'
    }
}
//第一个返回一个对象
//第二个返回undefine 因为第二个 return 后面没内容,分号自动加载 return 后面
复制代码

判断一个数字是否是整数

//es6
Number.isInteger()
//非es6
function isInteger(x) {
    return (x^0) === x;
}
复制代码

写一个sum方法,在使用任意语法调用时,都可以正常工作

//方法一
function sum(x) {
    if(arguments.length === 2){
        return arguments[0] + arguments[1];
    }else{
        return function (y) {
            return x+y
        }
    }
}
//方法二
function sum2(x,y) {
    if(y !== undefined){
        return x+y;
    }else{
        return function (y) {
            x+y;
        }
    }
}
复制代码

下面的代码将输出什么内容到控制台?

var myObject = {
    foo:'bar',
    func:function(){
        var self = this;
        console.log("outer func: this.foo = " + this.foo);
        console.log("outer func: self.foo =" + self.foo);
        (function(){
            console.log("inner func: this.foo="+this.foo);
            console.log("inner func: self.foo="+self.foo);
        }())
    }
}
//输出
outer func: this.foo = bar
outer func:self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
复制代码

下面的代码将输出什么?闭包在这里能起什么作用?

for(var i=0;i<5;i++){
    (function(){
       setTimeout(function(){
        console.log(i)
       },i*1000) 
    }())
}
//输出  5 5 5 5 5
//原因:在循环中执行的每个函数将先整个循环完成之后执行,因此,将会引用存储在i中的最后一个值,那就是5

//闭包可以为每次迭代创建一个唯一的作用域,存储作用域内的循环变量,如下代码会按预期输出0、1、2、3、4到控制台
for(var i=0;i<5;i++){
    (function(x){
        setTimeout(function(){
            console.log(x)
        },x*1000) 
    })(i)
}
复制代码

一下代码行将输出什么到控制台

console.log("0 || 1 ="+(0 || 1));
console.log("1 || 2 ="+(1 || 2));
console.log("0 && 1 ="+(0 && 1));
console.log("1 && 2 ="+(1 && 2));
//输出
//0 || 1 = 1;
//1 || 2 = 1;
//0 && 1 = 0;
//1 && 2 = 2 
复制代码

以下代码将输出什么?

var a={},b={key:'b'},c={key:'c'};
a[b] = 123;
a[c] = 456;
console.log(a[b]);
//输出 456 
//当设置对象属性时,JavaScript 会隐式地将[]内的变量转换成字符串,在这种情况下,由于b和c都是对象,
因此它们都将被转换为[object Object]。结果就是,a[b]和a[c]均相当于a["[object Object]"],
并可以互换使用。因此,设置或引用a[c]和设置或引用a[b]完全相同。
复制代码

防抖

防抖是将多次执行操作转变成一次

/**
 * underscore 防抖函数,返回函数连续调用时,空闲时间必须大于或等于 wait,func 才会执行
 *
 * @param  {function} func        回调函数
 * @param  {number}   wait        表示时间窗口的间隔
 * @param  {boolean}  immediate   设置为ture时,是否立即调用函数
 * @return {function}             返回客户调用函数
 */
_.debounce = function(func, wait, immediate) {
    var timeout, args, context, timestamp, result;

    var later = function() {
      // 现在和上一次时间戳比较
      var last = _.now() - timestamp;
      // 如果当前间隔时间少于设定时间且大于0就重新设置定时器
      if (last < wait && last >= 0) {
        timeout = setTimeout(later, wait - last);
      } else {
        // 否则的话就是时间到了执行回调函数
        timeout = null;
        if (!immediate) {
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        }
      }
    };

    return function() {
      context = this;
      args = arguments;
      // 获得时间戳
      timestamp = _.now();
      // 如果定时器不存在且立即执行函数
      var callNow = immediate && !timeout;
      // 如果定时器不存在就创建一个
      if (!timeout) timeout = setTimeout(later, wait);
      if (callNow) {
        // 如果需要立即执行函数的话 通过 apply 执行
        result = func.apply(context, args);
        context = args = null;
      }

      return result;
    };
  };
复制代码

节流

节流是将多次执行变成每隔一段时间执行

/**
 * underscore 节流函数,返回函数连续调用时,func 执行频率限定为 次 / wait
 *
 * @param  {function}   func      回调函数
 * @param  {number}     wait      表示时间窗口的间隔
 * @param  {object}     options   如果想忽略开始函数的的调用,传入{leading: false}。
 *                                如果想忽略结尾函数的调用,传入{trailing: false}
 *                                两者不能共存,否则函数不能执行
 * @return {function}             返回客户调用函数   
 */
_.throttle = function(func, wait, options) {
    var context, args, result;
    var timeout = null;
    // 之前的时间戳
    var previous = 0;
    // 如果 options 没传则设为空对象
    if (!options) options = {};
    // 定时器回调函数
    var later = function() {
      // 如果设置了 leading,就将 previous 设为 0
      // 用于下面函数的第一个 if 判断
      previous = options.leading === false ? 0 : _.now();
      // 置空一是为了防止内存泄漏,二是为了下面的定时器判断
      timeout = null;
      result = func.apply(context, args);
      if (!timeout) context = args = null;
    };
    return function() {
      // 获得当前时间戳
      var now = _.now();
      // 首次进入前者肯定为 true
	  // 如果需要第一次不执行函数
	  // 就将上次时间戳设为当前的
      // 这样在接下来计算 remaining 的值时会大于0
      if (!previous && options.leading === false) previous = now;
      // 计算剩余时间
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      // 如果当前调用已经大于上次调用时间 + wait
      // 或者用户手动调了时间
 	  // 如果设置了 trailing,只会进入这个条件
	  // 如果没有设置 leading,那么第一次会进入这个条件
	  // 还有一点,你可能会觉得开启了定时器那么应该不会进入这个 if 条件了
	  // 其实还是会进入的,因为定时器的延时
	  // 并不是准确的时间,很可能你设置了2秒
	  // 但是他需要2.2秒才触发,这时候就会进入这个条件
      if (remaining <= 0 || remaining > wait) {
        // 如果存在定时器就清理掉否则会调用二次回调
        if (timeout) {
          clearTimeout(timeout);
          timeout = null;
        }
        previous = now;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      } else if (!timeout && options.trailing !== false) {
        // 判断是否设置了定时器和 trailing
	    // 没有的话就开启一个定时器
        // 并且不能不能同时设置 leading 和 trailing
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };
复制代码

转载于:https://juejin.im/post/5c664bb0e51d45403f2a989d

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值