前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >那些高级前端是如何回答面试题的_2023-02-24

那些高级前端是如何回答面试题的_2023-02-24

原创
作者头像
gogo2027
发布于 2023-02-24 00:42:21
发布于 2023-02-24 00:42:21
56600
代码可运行
举报
运行总次数:0
代码可运行

防抖节流

题目描述:手写防抖节流

实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 防抖
function debounce(fn, delay = 300) {
  //默认300毫秒
  let timer;
  return function () {
    const args = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, args); // 改变this指向为调用debounce所指的对象
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  debounce(() => {
    console.log(111);
  }, 1000)
);

// 节流
// 设置一个标志
function throttle(fn, delay) {
  let flag = true;
  return () => {
    if (!flag) return;
    flag = false;
    timer = setTimeout(() => {
      fn();
      flag = true;
    }, delay);
  };
}

window.addEventListener(
  "scroll",
  throttle(() => {
    console.log(111);
  }, 1000)
);

你在工作终于到那些问题,解决方法是什么

代码语言:perl
AI代码解释
复制
经常遇到的问题就是Cannot read property ‘prototype’ of undefined
解决办法通过浏览器报错提示代码定位问题,解决问题

Vue项目中遇到视图不更新,方法不执行,埋点不触发等问题
一般解决方案查看浏览器报错,查看代码运行到那个阶段未之行结束,阅读源码以及相关文档等
然后举出来最近开发的项目中遇到的算是两个比较大的问题。

数组扁平化

题目描述:实现一个方法使多维数组变成一维数组

最常见的递归版本如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function flatter(arr) {
  if (!arr.length) return;
  return arr.reduce(
    (pre, cur) =>
      Array.isArray(cur) ? [...pre, ...flatter(cur)] : [...pre, cur],
    []
  );
}
// console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));

扩展思考:能用迭代的思路去实现吗?

实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function flatter(arr) {
  if (!arr.length) return;
  while (arr.some((item) => Array.isArray(item))) {
    arr = [].concat(...arr);
  }
  return arr;
}
// console.log(flatter([1, 2, [1, [2, 3, [4, 5, [6]]]]]));

instance 如何使用

左边可以是任意值,右边只能是函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
'hello tuture' instanceof String // false

10 个 Ajax 同时发起请求,全部返回展示结果,并且至多允许三次失败,说出设计思路

这个问题相信很多人会第一时间想到 Promise.all ,但是这个函数有一个局限在于如果失败一次就返回了,直接这样实现会有点问题,需要变通下。以下是两种实现思路

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 以下是不完整代码,着重于思路 非 Promise 写法
let successCount = 0
let errorCount = 0
let datas = []
ajax(url, (res) => {
     if (success) {
         success++
         if (success + errorCount === 10) {
             console.log(datas)
         } else {
             datas.push(res.data)
         }
     } else {
         errorCount++
         if (errorCount > 3) {
            // 失败次数大于3次就应该报错了
             throw Error('失败三次')
         }
     }
})
// Promise 写法
let errorCount = 0
let p = new Promise((resolve, reject) => {
    if (success) {
         resolve(res.data)
     } else {
         errorCount++
         if (errorCount > 3) {
            // 失败次数大于3次就应该报错了
            reject(error)
         } else {
             resolve(error)
         }
     }
})
Promise.all([p]).then(v => {
  console.log(v);
});

函数防抖

触发高频事件 N 秒后只会执行一次,如果 N 秒内事件再次触发,则会重新计时。

简单版:函数内部支持使用 this 和 event 对象;

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function debounce(func, wait) {
    var timeout;
    return function () {
        var context = this;
        var args = arguments;
        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}

使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var node = document.getElementById('layout')
function getUserAction(e) {
    console.log(this, e)  // 分别打印:node 这个节点 和 MouseEvent
    node.innerHTML = count++;
};
node.onmousemove = debounce(getUserAction, 1000)

最终版:除了支持 this 和 event 外,还支持以下功能:

  • 支持立即执行;
  • 函数可能有返回值;
  • 支持取消功能;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function debounce(func, wait, immediate) {
    var timeout, result;

    var debounced = function () {
        var context = this;
        var args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            // 如果已经执行过,不再执行
            var callNow = !timeout;
            timeout = setTimeout(function(){
                timeout = null;
            }, wait)
            if (callNow) result = func.apply(context, args)
        } else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
        return result;
    };

    debounced.cancel = function() {
        clearTimeout(timeout);
        timeout = null;
    };

    return debounced;
}

使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var setUseAction = debounce(getUserAction, 10000, true);
// 使用防抖
node.onmousemove = setUseAction

// 取消防抖
setUseAction.cancel()

参考 前端进阶面试题详细解答

为什么需要清除浮动?清除浮动的方式

浮动的定义: 非IE浏览器下,容器不设高度且子元素浮动时,容器高度不能被内容撑开。 此时,内容会溢出到容器外面而影响布局。这种现象被称为浮动(溢出)。

浮动的工作原理:

  • 浮动元素脱离文档流,不占据空间(引起“高度塌陷”现象)
  • 浮动元素碰到包含它的边框或者其他浮动元素的边框停留

浮动元素可以左右移动,直到遇到另一个浮动元素或者遇到它外边缘的包含框。浮动框不属于文档流中的普通流,当元素浮动之后,不会影响块级元素的布局,只会影响内联元素布局。此时文档流中的普通流就会表现得该浮动框不存在一样的布局模式。当包含框的高度小于浮动框的时候,此时就会出现“高度塌陷”。

浮动元素引起的问题?

  • 父元素的高度无法被撑开,影响与父元素同级的元素
  • 与浮动元素同级的非浮动元素会跟随其后
  • 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构

清除浮动的方式如下:

  • 给父级div定义height属性
  • 最后一个浮动元素之后添加一个空的div标签,并添加clear:both样式
  • 包含浮动元素的父级标签添加overflow:hidden或者overflow:auto
  • 使用 :after 伪元素。由于IE6-7不支持 :after,使用 zoom:1 触发 hasLayout**
代码语言:css
AI代码解释
复制
.clearfix:after{
    content: "\200B";
    display: table; 
    height: 0;
    clear: both;
  }
  .clearfix{
    *zoom: 1;
  }

动态规划求解硬币找零问题

题目描述:给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
示例1输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1

示例2输入: coins = [2], amount = 3
输出: -1

实现代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const coinChange = function (coins, amount) {
  // 用于保存每个目标总额对应的最小硬币个数
  const f = [];
  // 提前定义已知情况
  f[0] = 0;
  // 遍历 [1, amount] 这个区间的硬币总额
  for (let i = 1; i <= amount; i++) {
    // 求的是最小值,因此我们预设为无穷大,确保它一定会被更小的数更新
    f[i] = Infinity;
    // 循环遍历每个可用硬币的面额
    for (let j = 0; j < coins.length; j++) {
      // 若硬币面额小于目标总额,则问题成立
      if (i - coins[j] >= 0) {
        // 状态转移方程
        f[i] = Math.min(f[i], f[i - coins[j]] + 1);
      }
    }
  }
  // 若目标总额对应的解为无穷大,则意味着没有一个符合条件的硬币总数来更新它,本题无解,返回-1
  if (f[amount] === Infinity) {
    return -1;
  }
  // 若有解,直接返回解的内容
  return f[amount];
};

实现函数原型方法

call

使用一个指定的 this 值和一个或多个参数来调用一个函数。

实现要点:

  • this 可能传入 null;
  • 传入不固定个数的参数;
  • 函数可能有返回值;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

apply

apply 和 call 一样,唯一的区别就是 call 是传入不固定个数的参数,而 apply 是传入一个数组。

实现要点:

  • this 可能传入 null;
  • 传入一个数组;
  • 函数可能有返回值;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.apply2 = function (context, arr) {
    var context = context || window;
    context.fn = this;

    var result;
    if (!arr) {
        result = context.fn();
    } else {
        var args = [];
        for (var i = 0, len = arr.length; i < len; i++) {
            args.push('arr[' + i + ']');
        }
        result = eval('context.fn(' + args + ')')
    }

    delete context.fn
    return result;
}

bind

bind 方法会创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

实现要点:

  • bind() 除了 this 外,还可传入多个参数;
  • bing 创建的新函数可能传入多个参数;
  • 新函数可能被当做构造函数调用;
  • 函数可能有返回值;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Function.prototype.bind2 = function (context) {
    var self = this;
    var args = Array.prototype.slice.call(arguments, 1);

    var fNOP = function () {};

    var fBound = function () {
        var bindArgs = Array.prototype.slice.call(arguments);
        return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
    }

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();
    return fBound;
}

实现 new 关键字

new 运算符用来创建用户自定义的对象类型的实例或者具有构造函数的内置对象的实例。

实现要点:

  • new 会产生一个新对象;
  • 新对象需要能够访问到构造函数的属性,所以需要重新指定它的原型;
  • 构造函数可能会显示返回;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function objectFactory() {
    var obj = new Object()
    Constructor = [].shift.call(arguments);
    obj.__proto__ = Constructor.prototype;
    var ret = Constructor.apply(obj, arguments);

    // ret || obj 这里这么写考虑了构造函数显示返回 null 的情况
    return typeof ret === 'object' ? ret || obj : obj;
};

使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function person(name, age) {
    this.name = name
    this.age = age
}
let p = objectFactory(person, '布兰', 12)
console.log(p)  // { name: '布兰', age: 12 }

实现 instanceof 关键字

instanceof 就是判断构造函数的 prototype 属性是否出现在实例的原型链上。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function instanceOf(left, right) {
    let proto = left.__proto__
    while (true) {
        if (proto === null) return false
        if (proto === right.prototype) {
            return true
        }
        proto = proto.__proto__
    }
}

上面的 left.proto 这种写法可以换成 Object.getPrototypeOf(left)。

实现 Object.create

Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Object.create2 = function(proto, propertyObject = undefined) {
    if (typeof proto !== 'object' && typeof proto !== 'function') {
        throw new TypeError('Object prototype may only be an Object or null.')
    if (propertyObject == null) {
        new TypeError('Cannot convert undefined or null to object')
    }
    function F() {}
    F.prototype = proto
    const obj = new F()
    if (propertyObject != undefined) {
        Object.defineProperties(obj, propertyObject)
    }
    if (proto === null) {
        // 创建一个没有原型对象的对象,Object.create(null)
        obj.__proto__ = null
    }
    return obj
}

实现 Object.assign

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Object.assign2 = function(target, ...source) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object')
    }
    let ret = Object(target) 
    source.forEach(function(obj) {
        if (obj != null) {
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    ret[key] = obj[key]
                }
            }
        }
    })
    return ret
}

实现 JSON.stringify

JSON.stringify([, replacer , space) 方法是将一个 JavaScript 值(对象或者数组)转换为一个 JSON 字符串。此处模拟实现,不考虑可选的第二个参数 replacer 和第三个参数 space

  1. 基本数据类型:
    • undefined 转换之后仍是 undefined(类型也是 undefined)
    • boolean 值转换之后是字符串 "false"/"true"
    • number 类型(除了 NaN 和 Infinity)转换之后是字符串类型的数值
    • symbol 转换之后是 undefined
    • null 转换之后是字符串 "null"
    • string 转换之后仍是string
    • NaN 和 Infinity 转换之后是字符串 "null"
  2. 函数类型:转换之后是 undefined
  3. 如果是对象类型(非函数)
    • 如果是一个数组:如果属性值中出现了 undefined、任意的函数以及 symbol,转换成字符串 "null" ;
    • 如果是 RegExp 对象:返回 {} (类型是 string);
    • 如果是 Date 对象,返回 Date 的 toJSON 字符串值;
    • 如果是普通对象;
      • 如果有 toJSON() 方法,那么序列化 toJSON() 的返回值。
      • 如果属性值中出现了 undefined、任意的函数以及 symbol 值,忽略。
      • 所有以 symbol 为属性键的属性都会被完全忽略掉。
  4. 对包含循环引用的对象(对象之间相互引用,形成无限循环)执行此方法,会抛出错误。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function jsonStringify(data) {
    let dataType = typeof data;

    if (dataType !== 'object') {
        let result = data;
        //data 可能是 string/number/null/undefined/boolean
        if (Number.isNaN(data) || data === Infinity) {
            //NaN 和 Infinity 序列化返回 "null"
            result = "null";
        } else if (dataType === 'function' || dataType === 'undefined' || dataType === 'symbol') {
            //function 、undefined 、symbol 序列化返回 undefined
            return undefined;
        } else if (dataType === 'string') {
            result = '"' + data + '"';
        }
        //boolean 返回 String()
        return String(result);
    } else if (dataType === 'object') {
        if (data === null) {
            return "null"
        } else if (data.toJSON && typeof data.toJSON === 'function') {
            return jsonStringify(data.toJSON());
        } else if (data instanceof Array) {
            let result = [];
            //如果是数组
            //toJSON 方法可以存在于原型链中
            data.forEach((item, index) => {
                if (typeof item === 'undefined' || typeof item === 'function' || typeof item === 'symbol') {
                    result[index] = "null";
                } else {
                    result[index] = jsonStringify(item);
                }
            });
            result = "[" + result + "]";
            return result.replace(/'/g, '"');

        } else {
            //普通对象
            /**             * 循环引用抛错(暂未检测,循环引用时,堆栈溢出)             * symbol key 忽略             * undefined、函数、symbol 为属性值,被忽略             */
            let result = [];
            Object.keys(data).forEach((item, index) => {
                if (typeof item !== 'symbol') {
                    //key 如果是symbol对象,忽略
                    if (data[item] !== undefined && typeof data[item] !== 'function'
                        && typeof data[item] !== 'symbol') {
                        //键值如果是 undefined、函数、symbol 为属性值,忽略
                        result.push('"' + item + '"' + ":" + jsonStringify(data[item]));
                    }
                }
            });
            return ("{" + result + "}").replace(/'/g, '"');
        }
    }
}

实现 JSON.parse

介绍 2 种方法实现:

  • eval 实现;
  • new Function 实现;

eval 实现

第一种方式最简单,也最直观,就是直接调用 eval,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var json = '{"a":"1", "b":2}';
var obj = eval("(" + json + ")");  // obj 就是 json 反序列化之后得到的对象

但是直接调用 eval 会存在安全问题,如果数据中可能不是 json 数据,而是可执行的 JavaScript 代码,那很可能会造成 XSS 攻击。因此,在调用 eval 之前,需要对数据进行校验。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var rx_one = /^[\],:{}\s]*$/;
var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
var rx_four = /(?:^|:|,)(?:\s*\[)+/g;

if (
    rx_one.test(
        json.replace(rx_two, "@")
            .replace(rx_three, "]")
            .replace(rx_four, "")
    )
) {
    var obj = eval("(" +json + ")");
}

new Function 实现

Function 与 eval 有相同的字符串参数特性。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var json = '{"name":"小姐姐", "age":20}';
var obj = (new Function('return ' + json))();

实现 Promise

实现 Promise 需要完全读懂 Promise A+ 规范,不过从总体的实现上看,有如下几个点需要考虑到:

  • then 需要支持链式调用,所以得返回一个新的 Promise;
  • 处理异步问题,所以得先用 onResolvedCallbacks 和 onRejectedCallbacks 分别把成功和失败的回调存起来;
  • 为了让链式调用正常进行下去,需要判断 onFulfilled 和 onRejected 的类型;
  • onFulfilled 和 onRejected 需要被异步调用,这里用 setTimeout 模拟异步;
  • 处理 Promise 的 resolve;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class Promise {
    constructor(executor) {
        this.status = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedCallbacks = [];
        this.onRejectedCallbacks = [];

        let resolve = (value) = > {
            if (this.status === PENDING) {
                this.status = FULFILLED;
                this.value = value;
                this.onResolvedCallbacks.forEach((fn) = > fn());
            }
        };

        let reject = (reason) = > {
            if (this.status === PENDING) {
                this.status = REJECTED;
                this.reason = reason;
                this.onRejectedCallbacks.forEach((fn) = > fn());
            }
        };

        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

    then(onFulfilled, onRejected) {
        // 解决 onFufilled,onRejected 没有传值的问题
        onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (v) = > v;
        // 因为错误的值要让后面访问到,所以这里也要抛出错误,不然会在之后 then 的 resolve 中捕获
        onRejected = typeof onRejected === "function" ? onRejected : (err) = > {
            throw err;
        };
        // 每次调用 then 都返回一个新的 promise
        let promise2 = new Promise((resolve, reject) = > {
            if (this.status === FULFILLED) {
                //Promise/A+ 2.2.4 --- setTimeout
                setTimeout(() = > {
                    try {
                        let x = onFulfilled(this.value);
                        // x可能是一个proimise
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }

            if (this.status === REJECTED) {
                //Promise/A+ 2.2.3
                setTimeout(() = > {
                    try {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            }

            if (this.status === PENDING) {
                this.onResolvedCallbacks.push(() = > {
                    setTimeout(() = > {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });

                this.onRejectedCallbacks.push(() = > {
                    setTimeout(() = > {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    }, 0);
                });
            }
        });

        return promise2;
    }
}
const resolvePromise = (promise2, x, resolve, reject) = > {
    // 自己等待自己完成是错误的实现,用一个类型错误,结束掉 promise  Promise/A+ 2.3.1
    if (promise2 === x) {
        return reject(
            new TypeError("Chaining cycle detected for promise #<Promise>"));
    }
    // Promise/A+ 2.3.3.3.3 只能调用一次
    let called;
    // 后续的条件要严格判断 保证代码能和别的库一起使用
    if ((typeof x === "object" && x != null) || typeof x === "function") {
        try {
            // 为了判断 resolve 过的就不用再 reject 了(比如 reject 和 resolve 同时调用的时候)  Promise/A+ 2.3.3.1
            let then = x.then;
            if (typeof then === "function") {
            // 不要写成 x.then,直接 then.call 就可以了 因为 x.then 会再次取值,Object.defineProperty  Promise/A+ 2.3.3.3
                then.call(
                    x, (y) = > {
                        // 根据 promise 的状态决定是成功还是失败
                        if (called) return;
                        called = true;
                        // 递归解析的过程(因为可能 promise 中还有 promise) Promise/A+ 2.3.3.3.1
                        resolvePromise(promise2, y, resolve, reject);
                    }, (r) = > {
                        // 只要失败就失败 Promise/A+ 2.3.3.3.2
                        if (called) return;
                        called = true;
                        reject(r);
                    });
            } else {
                // 如果 x.then 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.3.4
                resolve(x);
            }
        } catch (e) {
            // Promise/A+ 2.3.3.2
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        // 如果 x 是个普通值就直接返回 resolve 作为结果  Promise/A+ 2.3.4
        resolve(x);
    }
};

Promise 写完之后可以通过 promises-aplus-tests 这个包对我们写的代码进行测试,看是否符合 A+ 规范。不过测试前还得加一段代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// promise.js
// 这里是上面写的 Promise 全部代码
Promise.defer = Promise.deferred = function () {
    let dfd = {}
    dfd.promise = new Promise((resolve,reject)=>{
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}
module.exports = Promise;

全局安装:

代码语言:shell
AI代码解释
复制
npm i promises-aplus-tests -g

终端下执行验证命令:

代码语言:shell
AI代码解释
复制
promises-aplus-tests promise.js

上面写的代码可以顺利通过全部 872 个测试用例。

Promise.resolve

Promsie.resolve(value) 可以将任何值转成值为 value 状态是 fulfilled 的 Promise,但如果传入的值本身是 Promise 则会原样返回它。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.resolve = function(value) {
    // 如果是 Promsie,则直接输出它
    if(value instanceof Promise){
        return value
    }
    return new Promise(resolve => resolve(value))
}

Promise.reject

和 Promise.resolve() 类似,Promise.reject() 会实例化一个 rejected 状态的 Promise。但与 Promise.resolve() 不同的是,如果给 Promise.reject() 传递一个 Promise 对象,则这个对象会成为新 Promise 的值。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.reject = function(reason) {
    return new Promise((resolve, reject) => reject(reason))
}

Promise.all

Promise.all 的规则是这样的:

  • 传入的所有 Promsie 都是 fulfilled,则返回由他们的值组成的,状态为 fulfilled 的新 Promise;
  • 只要有一个 Promise 是 rejected,则返回 rejected 状态的新 Promsie,且它的值是第一个 rejected 的 Promise 的值;
  • 只要有一个 Promise 是 pending,则返回一个 pending 状态的新 Promise;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.all = function(promiseArr) {
    let index = 0, result = []
    return new Promise((resolve, reject) => {
        promiseArr.forEach((p, i) => {
            Promise.resolve(p).then(val => {
                index++
                result[i] = val
                if (index === promiseArr.length) {
                    resolve(result)
                }
            }, err => {
                reject(err)
            })
        })
    })
}

Promise.race

Promise.race 会返回一个由所有可迭代实例中第一个 fulfilled 或 rejected 的实例包装后的新实例。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.race = function(promiseArr) {
    return new Promise((resolve, reject) => {
        promiseArr.forEach(p => {
            Promise.resolve(p).then(val => {
                resolve(val)
            }, err => {
                rejecte(err)
            })
        })
    })
}

Promise.allSettled

Promise.allSettled 的规则是这样:

  • 所有 Promise 的状态都变化了,那么新返回一个状态是 fulfilled 的 Promise,且它的值是一个数组,数组的每项由所有 Promise 的值和状态组成的对象;
  • 如果有一个是 pending 的 Promise,则返回一个状态是 pending 的新实例;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.allSettled = function(promiseArr) {
    let result = []

    return new Promise((resolve, reject) => {
        promiseArr.forEach((p, i) => {
            Promise.resolve(p).then(val => {
                result.push({
                    status: 'fulfilled',
                    value: val
                })
                if (result.length === promiseArr.length) {
                    resolve(result) 
                }
            }, err => {
                result.push({
                    status: 'rejected',
                    reason: err
                })
                if (result.length === promiseArr.length) {
                    resolve(result) 
                }
            })
        })  
    })   
}

Promise.any

Promise.any 的规则是这样:

  • 空数组或者所有 Promise 都是 rejected,则返回状态是 rejected 的新 Promsie,且值为 AggregateError 的错误;
  • 只要有一个是 fulfilled 状态的,则返回第一个是 fulfilled 的新实例;
  • 其他情况都会返回一个 pending 的新实例;
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.any = function(promiseArr) {
    let index = 0
    return new Promise((resolve, reject) => {
        if (promiseArr.length === 0) return 
        promiseArr.forEach((p, i) => {
            Promise.resolve(p).then(val => {
                resolve(val)

            }, err => {
                index++
                if (index === promiseArr.length) {
                  reject(new AggregateError('All promises were rejected'))
                }
            })
        })
    })
}

虚拟DOM转换成真实DOM

描述:将如下 JSON格式的虚拟DOM结构转换成真实DOM结构。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// vnode 结构
{
    tag: 'DIV',
    attrs: {
        id: "app"
    },
    children: [
        {
            tag: 'SPAN',
            children: [
                {
                    tag: 'A',
                    children: []
                }
            ]
        }
    ]
}
// 真实DOM 结构
<div id="app">
    <span>
        <a></a>
    </span>
</div>

实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function _render(vnode) {
    // 如果是数字类型转化为字符串;
    if(typeof vnode === "number") {
        vnode = String(vnode);
    }
    // 字符串类型直接就是文本节点
    if(typeof vnode === "string") {
        return document.createTextNode(vnode);
    }
    // 普通 DOM
    const dom = document.createElement(vnode.tag);
    if(vnode.attrs) {
        // 遍历属性
        Object.keys(vnode.attrs).forEach((key) => {
            dom.setAttribute(key, vnode.attrs[key]);
        });
    }
    // 子数组进行递归操作
    vnode.children.forEach((child) => dom.appendChild(_render(child)));
    return dom;
}

// 测试
let vnode = {
    tag: "DIV",
    attrs: {
        id: "app",
    },
    children: [
        {
            tag: "SPAN",
            children: [
                {
                    tag: "A",
                    children: [],
                },
            ],
        },
    ],
};
console.log(_render(vnode)); // <div id="app"><span><a></a></span></div>

Set 和 Map有什么区别?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1、Map是键值对,Set是值得集合,当然键和值可以是任何得值
2、Map可以通过get方法获取值,而set不能因为它只有值
3、都能通过迭代器进行for...of 遍历
4、Set的值是唯一的可以做数组去重,而Map由于没有格式限制,可以做数据存储

说一下for...in 和 for...of的区别?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for...of遍历获取的是对象的键值, for...in获取的是对象的键名;
for...in会遍历对象的整个原型链, 性能非常差不推荐使用,for...of只遍历当前对象不会遍历原型链;
对于数组的遍历,for...in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for...of只返回数组的下标对应的属性值;
总结:for...in循环主要是为了遍历对象而生,不适用遍历数组; for....of循环可以用来遍历数组、类数组对象、字符串、Set、Map以及Generator对象

发布订阅模式(事件总线)

描述:实现一个发布订阅模式,拥有 on, emit, once, off 方法

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class EventEmitter {
    constructor() {
        // 包含所有监听器函数的容器对象
        // 内部结构: {msg1: [listener1, listener2], msg2: [listener3]}
        this.cache = {};
    }
    // 实现订阅
    on(name, callback) {
        if(this.cache[name]) {
            this.cache[name].push(callback);
        }
        else {
            this.cache[name] = [callback];
        }
    }
    // 删除订阅
    off(name, callback) {
        if(this.cache[name]) {
            this.cache[name] = this.cache[name].filter(item => item !== callback);
        }
        if(this.cache[name].length === 0) delete this.cache[name];
    }
    // 只执行一次订阅事件
    once(name, callback) {
        callback();
        this.off(name, callback);
    }
    // 触发事件
    emit(name, ...data) {
        if(this.cache[name]) {
            // 创建副本,如果回调函数内继续注册相同事件,会造成死循环
            let tasks = this.cache[name].slice();
            for(let fn of tasks) {
                fn(...data);
            }
        }
    }
}

PWA使用过吗?serviceWorker的使用原理是啥?

渐进式网络应用(PWA)是谷歌在2015年底提出的概念。基本上算是web应用程序,但在外观和感觉上与原生app类似。支持PWA的网站可以提供脱机工作、推送通知和设备硬件访问等功能。

Service Worker是浏览器在后台独立于网页运行的脚本,它打开了通向不需要网页或用户交互的功能的大门。 现在,它们已包括如推送通知和后台同步等功能。 将来,Service Worker将会支持如定期同步或地理围栏等其他功能。 本教程讨论的核心功能是拦截和处理网络请求,包括通过程序来管理缓存中的响应。

原函数形参不定长(此时 fn.length 为0)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function curry(fn) {
    // 保存参数,除去第一个函数参数
    let args = [].slice.call(arguments, 1);
    // 返回一个新函数
    let curried = function () {
        // 新函数调用时会继续传参
        let allArgs = [...args, ...arguments];
        return curry(fn, ...allArgs);
    };
    // 利用toString隐式转换的特性,当最后执行函数时,会隐式转换
    curried.toString = function () {
        return fn(...args);
    };
    return curried;
}

// 测试
function add(...args) {
  return args.reduce((pre, cur) => pre + cur, 0);
}
console.log(add(1, 2, 3, 4));
let addCurry = curry(add);
console.log(addCurry(1)(2)(3) == 6); // true
console.log(addCurry(1, 2, 3)(4) == 10); // true
console.log(addCurry(2, 6)(1).toString()); // 9
console.log(addCurry(2, 6)(1, 8)); // 打印 curried 函数

说一下常见的HTTP状态码?说一下状态码是302和304是什么意思?你在项目中出现过么?你是怎么解决的?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <!-- 状态码:由3位数字组成,第一个数字定义了响应的类别 -->
    <!-- 1xx:指示消息,表示请求已接收,继续处理 -->
    <!-- 2xx:成功,表示请求已被成功接收,处理 -->
    <!-- 200 OK:客户端请求成功
         204 No Content:无内容。服务器成功处理,但未返回内容。一般用在只是客户端向服务器发送信息,而服务器不用向客户端返回什么信息的情况。不会刷新页面。
         206 Partial Content:服务器已经完成了部分GET请求(客户端进行了范围请求)。响应报文中包含Content-Range指定范围的实体内容
 -->
    <!-- 3xx 重定向 -->
    <!-- 301 Moved Permanently:永久重定向,表示请求的资源已经永久的搬到了其他位置。
         302 Found:临时重定向,表示请求的资源临时搬到了其他位置
         303 See Other:临时重定向,应使用GET定向获取请求资源。303功能与302一样,区别只是303明确客户端应该使用GET访问
         307 Temporary Redirect:临时重定向,和302有着相同含义。POST不会变成GET
         304 Not Modified:表示客户端发送附带条件的请求(GET方法请求报文中的IF…)时,条件不满足。返回304时,不包含任何响应主体。虽然304被划分在3XX,但和重定向一毛钱关系都没有
 -->
    <!-- 4xx:客户端错误 -->
    <!-- 400 Bad Request:客户端请求有语法错误,服务器无法理解。
         401 Unauthorized:请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用。
         403 Forbidden:服务器收到请求,但是拒绝提供服务
         404 Not Found:请求资源不存在。比如,输入了错误的url
         415 Unsupported media type:不支持的媒体类型
 -->
    <!-- 5xx:服务器端错误,服务器未能实现合法的请求。 -->
    <!-- 500 Internal Server Error:服务器发生不可预期的错误。
         503 Server Unavailable:服务器当前不能处理客户端的请求,一段时间后可能恢复正常,
 -->

说一下常见的git操作

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git branch 查看本地所有分支
git status 查看当前状态 
git commit 提交 
git branch -a 查看所有的分支
git branch -r 查看远程所有分支
git commit -am "nit" 提交并且加注释 
git remote add origin git@192.168.1.119:ndshow
git push origin master 将文件给推到服务器上 
git remote show origin 显示远程库origin里的资源 
git push origin master:develop
git push origin master:hb-dev 将本地库与服务器上的库进行关联 
git checkout --track origin/dev 切换到远程dev分支
git branch -D master develop 删除本地库develop
git checkout -b dev 建立一个新的本地分支dev
git merge origin/dev 将分支dev与当前分支进行合并
git checkout dev 切换到本地dev分支
git remote show 查看远程库
git add .
git rm 文件名(包括路径) 从git中删除指定文件
git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来
git config --list 看所有用户
git ls-files 看已经被提交的
git rm [file name] 删除一个文件
git commit -a 提交当前repos的所有的改变
git add [file name] 添加一个文件到git index
git commit -v 当你用-v参数的时候可以看commit的差异
git commit -m "This is the message describing the commit" 添加commit信息
git commit -a -a是代表add,把所有的change加到git index里然后再commit
git commit -a -v 一般提交命令
git log 看你commit的日志
git diff 查看尚未暂存的更新
git rm a.a 移除文件(从暂存区和工作区中删除)
git rm --cached a.a 移除文件(只从暂存区中删除)
git commit -m "remove" 移除文件(从Git中删除)
git rm -f a.a 强行移除修改后文件(从暂存区和工作区中删除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 将文件给push到一个临时空间中
git stash pop 将文件从临时空间pop下来

Promise.reject

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Promise.reject = function(reason) {
    return new Promise((resolve, reject) => reject(reason));
}

Vuex有哪些基本属性?为什么 Vuex 的 mutation 中不能做异步操作?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
有五种,分别是 State、 Getter、Mutation 、Action、 Module
1、state => 基本数据(数据源存放地)
2、getters => 从基本数据派生出来的数据
3、mutations => 提交更改数据的方法,同步
4、actions => 像一个装饰器,包裹mutations,使之可以异步。
5、modules => 模块化Vuex

1、Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样可以方便地跟踪每一个状态的变化,从而能够实现一些工具帮助更好地了解我们的应用。
2、每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。

详细说明 Event loop

众所周知 JS 是门非阻塞单线程语言,因为在最初 JS 就是为了和浏览器交互而诞生的。如果 JS 是门多线程的语言话,我们在多个线程中处理 DOM 就可能会发生问题(一个线程中新加节点,另一个线程中删除节点),当然可以引入读写锁解决这个问题。

JS 在执行的过程中会产生执行环境,这些执行环境会被顺序的加入到执行栈中。如果遇到异步的代码,会被挂起并加入到 Task(有多种 task) 队列中。一旦执行栈为空,Event Loop 就会从 Task 队列中拿出需要执行的代码并放入执行栈中执行,所以本质上来说 JS 中的异步还是同步行为。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

console.log('script end');

以上代码虽然 setTimeout 延时为 0,其实还是异步。这是因为 HTML5 标准规定这个函数第二个参数不得小于 4 毫秒,不足会自动增加。所以 setTimeout 还是会在 script end 之后打印。

不同的任务源会被分配到不同的 Task 队列中,任务源可以分为 微任务(microtask) 和 宏任务(macrotask)。在 ES6 规范中,microtask 称为 jobs,macrotask 称为 task

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

new Promise((resolve) => {
    console.log('Promise')
    resolve()
}).then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');
// script start => Promise => script end => promise1 => promise2 => setTimeout

以上代码虽然 setTimeout 写在 Promise 之前,但是因为 Promise 属于微任务而 setTimeout 属于宏任务,所以会有以上的打印。

微任务包括 process.nextTickpromiseObject.observeMutationObserver

宏任务包括 scriptsetTimeoutsetIntervalsetImmediateI/OUI rendering

很多人有个误区,认为微任务快于宏任务,其实是错误的。因为宏任务中包括了 script ,浏览器会先执行一个宏任务,接下来有异步代码的话就先执行微任务。

所以正确的一次 Event loop 顺序是这样的

  1. 执行同步代码,这属于宏任务
  2. 执行栈为空,查询是否有微任务需要执行
  3. 执行所有微任务
  4. 必要的话渲染 UI
  5. 然后开始下一轮 Event loop,执行宏任务中的异步代码

通过上述的 Event loop 顺序可知,如果宏任务中的异步代码有大量的计算并且需要操作 DOM 的话,为了更快的 界面响应,我们可以把操作 DOM 放入微任务中。

Node 中的 Event loop

Node 中的 Event loop 和浏览器中的不相同。

Node 的 Event loop 分为6个阶段,它们会按照顺序反复运行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<──connections───     │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
timer

timers 阶段会执行 setTimeoutsetInterval

一个 timer 指定的时间并不是准确时间,而是在达到这个时间后尽快执行回调,可能会因为系统正在执行别的事务而延迟。

下限的时间有一个范围:[1, 2147483647] ,如果设定的时间不在这个范围,将被设置为1。

I/O

I/O 阶段会执行除了 close 事件,定时器和 setImmediate 的回调

idle, prepare

idle, prepare 阶段内部实现

poll

poll 阶段很重要,这一阶段中,系统会做两件事情

  1. 执行到点的定时器
  2. 执行 poll 队列中的事件

并且当 poll 中没有定时器的情况下,会发现以下两件事情

  • 如果 poll 队列不为空,会遍历回调队列并同步执行,直到队列为空或者系统限制
  • 如果 poll 队列为空,会有两件事发生
    • 如果有 setImmediate 需要执行,poll 阶段会停止并且进入到 check 阶段执行 setImmediate
    • 如果没有 setImmediate 需要执行,会等待回调被加入到队列中并立即执行回调

如果有别的定时器需要被执行,会回到 timer 阶段执行回调。

check

check 阶段执行 setImmediate

close callbacks

close callbacks 阶段执行 close 事件

并且在 Node 中,有些情况下的定时器执行顺序是随机的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setTimeout(() => {
    console.log('setTimeout');
}, 0);
setImmediate(() => {
    console.log('setImmediate');
})
// 这里可能会输出 setTimeout,setImmediate
// 可能也会相反的输出,这取决于性能
// 因为可能进入 event loop 用了不到 1 毫秒,这时候会执行 setImmediate
// 否则会执行 setTimeout

当然在这种情况下,执行顺序是相同的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var fs = require('fs')

fs.readFile(__filename, () => {
    setTimeout(() => {
        console.log('timeout');
    }, 0);
    setImmediate(() => {
        console.log('immediate');
    });
});
// 因为 readFile 的回调在 poll 中执行
// 发现有 setImmediate ,所以会立即跳到 check 阶段执行回调
// 再去 timer 阶段执行 setTimeout
// 所以以上输出一定是 setImmediate,setTimeout

上面介绍的都是 macrotask 的执行情况,microtask 会在以上每个阶段完成后立即执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setTimeout(()=>{
    console.log('timer1')

    Promise.resolve().then(function() {
        console.log('promise1')
    })
}, 0)

setTimeout(()=>{
    console.log('timer2')

    Promise.resolve().then(function() {
        console.log('promise2')
    })
}, 0)

// 以上代码在浏览器和 node 中打印情况是不同的
// 浏览器中打印 timer1, promise1, timer2, promise2
// node 中打印 timer1, timer2, promise1, promise2

Node 中的 process.nextTick 会先于其他 microtask 执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setTimeout(() => {
  console.log("timer1");

  Promise.resolve().then(function() {
    console.log("promise1");
  });
}, 0);

process.nextTick(() => {
  console.log("nextTick");
});
// nextTick, timer1, promise1

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
哔哩哔哩H.265编码器在直播和点播的实践和应用
大家好,我是来自B站视频云技术部的技术专家叶天晓,今天和大家分享的主题是B站H.265编码器在直播和点播中的实践和应用。
LiveVideoStack
2019/12/17
4.3K0
哔哩哔哩H.265编码器在直播和点播的实践和应用
新知 | 腾讯明眸·极速高清 —— 更高清更低码率的媒体处理技术方案
今天的新知系列课,我们邀请到了来自腾讯明眸·极速高清团队的技术导师 —— 刘兆瑞,为大家介绍腾讯云音视频在视频编码优化以及工程落地上的一些新的方向。本次分享分为4个部分,包括当前媒体处理的行业趋势 ,腾讯明眸产品介绍,腾讯明眸·极速高清技术方案及其优化演进之路以及极速高清方案的未来发展之路。 本周五晚上7:30,我们将会在腾讯云音视频视频号、开源中国、InfoQ、51CTO、云+社区等多个平台进行第六期课程的直播,大家千万不要错过哦~ - 当前媒体处理的行业趋势 - 腾讯视频云作为头部云厂商,服
腾讯云音视频
2021/12/24
1.9K0
技术解码 | 视频云全链路媒体处理解决方案
随着近几年视频行业的爆发增长,各个业务场景对视频处理的需求越来越高。本周的技术解码就由段争志老师带大家一起探秘腾讯云视频云全链路媒体处理解决方案中的关键技术。 近几年视频行业喷井式爆发,短视频APP、社交媒体、电商带货、直播会议、线上教育等等各种泛媒体类应用大规模增长的同时,人们对高清/超高清、低延时、高画质的需求也越来越强烈。腾讯云视频云依托自身多年的视频技术的积累以及众多业务应用的落地优化实践,不断完善自身产品体系,优化性能,结合用户业务场景不断创新,提供一整套集视频质检、画质修复增强、编码、
腾讯云音视频
2020/08/17
2.6K0
腾讯视频云勇夺云端视频转码大赛多项第一
2021年2月21日,莫斯科国立大学(MoscowState University)举办的MSU云端视频转码大赛(CloudVideo Transcoding Services Comparison)成绩揭晓, 由腾讯内部开源协同的O264/V265编码器助力的视频云媒体处理 (Tencent Media Processing Service)业务,一举拿下H.264和H.265的视频转码质量、视频转码质量/转码速度(Best speed/quality trade-off)、视频转码质量/转码价格(
腾讯云音视频
2021/02/26
2.2K0
H.265在花椒直播中的应用与优化
本文由花椒直播技术总监唐赓在LiveVideoStack线上交流分享中的演讲内容整理而成。在分享中,唐赓详细介绍了花椒直播在两年多的H.265线上实践过程中所积累的一些经验,以及一些成本、效果优化方案
LiveVideoStack
2019/07/01
3.6K0
H.265在花椒直播中的应用与优化
SLC及MSU结果揭晓:腾讯云-媒体处理MPS产品全面领先
近期备受媒体处理界瞩目的两大评测结果出炉,以腾讯明眸为技术底座的腾讯云-媒体处理MPS在所参加的评测中,均取得了优异的成绩。其中7月7日Streaming Learning Center 发布的云厂商最新H.264 Per-title编码评测报告中,腾讯云-媒体处理MPS在所参评的三个大项中获得全部最优(Excellent);在5月25日最新发布的MSU云端转码评测中,腾讯云-媒体处理MPS在所参加的全部赛道(客观、主观、质量/成本 )所有比赛中(H.264、H.265、AV1)获得多项第一;值得一提的是,
腾讯云音视频
2022/07/26
1.2K0
SLC及MSU结果揭晓:腾讯云-媒体处理MPS产品全面领先
攻城狮手记 | 既高清又低码?腾讯明眸帮你两者兼得
随着近几年视频行业的井喷,短视频、社交媒体、电商带货、视频会议等泛媒体类应用大规模增长,人们对高画质、低延时的需求愈发强烈。 而腾讯明眸正是聚焦于“极速高清”和“画质重生”两大功能,利用腾讯云领先的编解码和媒体处理技术与AI技术融合打造的音视频技术品牌。在各类媒体业务中,腾讯明眸都能够为用户提供画质更好,码率更低的媒体处理服务。 下面我们就一同来了解一下这个让你能够“鱼与熊掌兼得”的黑科技以及它背后的工程师团队吧! “17年,音视频应用平台开始将关注点转向带宽成本、观看体验。我们也在这个时候开
腾讯云音视频
2021/09/28
1.2K0
腾讯V265编码器:给用户以完备的265体验
大家好,我是张贤国,毕业后长期从事于视频编码标准制定(HEVC、VVC),以及视频编码器(H.265)研发工作,2017年加入腾讯,主要负责视频编码研发相关工作。本次分享将重点介绍V265编码器的业务体验优化,包括码率控制优化以及业务适配相关的优化。主要内容可以分为三个部分,首先简单介绍V265的最新情况,然后重点讲解V265在码率控制方面所做的一些优化,最后会介绍V265编码器在业务落地过程中遇到的一些问题与解决方案。
LiveVideoStack
2019/09/17
4.9K0
腾讯V265编码器:给用户以完备的265体验
首次大规模应用!腾讯自研AV1编码器落地全民K歌
随着用户对高质量视频的需求不断增加,视频内容不断向超高清、高码率的方向发展,面对不断增长的成本,新一代视频编码技术的落地应用对平台变得尤为重要。作为老少咸宜的音乐娱乐社交平台,全民K歌APP中视频化内容在平台占比逐年增加,巨大的带宽成本同样给K歌团队带来了不小的压力。
腾讯云音视频
2023/12/09
9790
首次大规模应用!腾讯自研AV1编码器落地全民K歌
极速高清——给你带来全新的高清视野
很生气!!!我才刚落地,就因游戏界面糊了一下,阻止了我捡枪的步伐,就被不知道从哪蹿出来的家伙给打死了!!!瞬间落地成盒!!!
腾讯云音视频
2018/09/12
3.3K1
极速高清——给你带来全新的高清视野
新知 | 4K/8K超高清时代如何利用媒体处理技术加速媒体数字化升级
新知系列课程第二季来啦!我们将为大家带来全真互联时代下新的行业趋势、新的技术方向以及新的应用场景分享。本期我们邀请了腾讯云音视频技术导师——刘兆瑞,为大家分享媒体处理技术在4K/8K超高清视频处理上的应用。 随着观看设备分辨率的提升以及观看设备不断向高清升级,业界对视频清晰度的要求也日渐增高。中国电子信息产业发展研究院发表的《超高清视频产业发展白皮书(2021年)》宣告了超高清时代的来临。面对4K/8K超高分辨率、超高码率的视频,很多新的痛点问题亟待解决,今天的文章将分享我们在利用媒体处理能力加速媒体数字
腾讯云音视频
2022/09/26
7260
新知 | 4K/8K超高清时代如何利用媒体处理技术加速媒体数字化升级
AV1编码器速度和压缩率达到点播实用级别
时光飞逝,2019年的春天我们听着5G时代的呼喊,瞧着超高清趋势活泼的枝头,一幅春意盎然的大视频美景扑面而来。整个视频产业被推向高潮,其背后的视频编码技术功不可没,时下三个标准组织齐头并进,构成目前视频编码标准的主流:
LiveVideoStack
2021/09/01
2.3K0
揭秘熊猫TV HEVC直播
LiveVideoStack:熊猫直播HEVC直播间面向哪些用户,或哪些软件和硬件平台条件的用户开放?
LiveVideoStack
2021/09/02
1.9K0
微博短视频服务优化实践
我所在的团队主要负责微博短视频从客户端的转码上传到服务端的转码存储的整条服务链路。今天主要向大家分享我们团队在短视频方面有关视频编解码的实践与探索。
LiveVideoStack
2021/09/01
5810
快手智能视频图像编码处理服务架构
在视频服务飞速发展的今天,视频平台如何在兼顾机器带宽成本的同时,让用户获得更加极致的观看体验,是每一个视频技术团队都会面临的问题。
LiveVideoStack
2021/02/20
4.4K0
快手智能视频图像编码处理服务架构
视频技术入门指南
你真的理解视频技术吗?什么是帧率、分辨率、码率?它们之间有什么关系?你知道“1080p”和“4K”中的“p”和“K”代表什么吗?如何描述视频质量?蓝光光盘(Blu-ray Disc)究竟是什么?H.264/AVC、H.265/HEVC、AV1 等编解码器有什么区别?苹果的 Apple ProRes 又有什么特殊用途?HDR 和杜比视界(Dolby Vision)是什么?为什么视频文件有.mp4、.mkv、.flv 等多种后缀?
timerring
2025/02/11
1590
Shopee 视频处理技术后台应用
 点击上方“LiveVideoStack”关注我们 ▲扫描图中二维码或点击阅读原文▲ 了解音视频技术大会更多信息 目录 1. 背景 2. Shopee 视频技术落地产品 3. Shopee 视频相关后台服务     3.1 直播/点播转码     3.2 直播连麦     3.3 多人会议混流     3.4 视频后台编辑 4. 高清低码     4.1 视频处理的一般流程     4.2 Shopee 高清低码优化方案 5. 性能优化     5.1 编码器端上优化     5.2 一入多出编码 东
LiveVideoStack
2023/04/04
6340
Shopee 视频处理技术后台应用
你问我答 | 云点播VOD(2021年8月-10月)
云点播VOD 你问我答 第10季 本期共解答10个问题 Q1:云点播视频播放失败如何排查? 视频播放失败有多种原因,定位问题的基本思路是: 配置网络抓包,查看网络请求情况。 查看浏览器控制台报错情况。 检查视频格式,使用的浏览器是否支持播放。 部分用户的原视频存在问题,可能导致视频上传后无法进行播放,建议用户在云点播进行一次转码后,使用转码后链接进行播放。 注意: 编码不是H.264编码的视频播放器无法播放,建议您转码为H.264编码的视频。 更多详情请参考[视频播放问题](https:
腾讯云音视频
2021/11/26
1.9K0
云直播开放支持AV1 & 音视频增强功能
疫情之后,各行各业都开始积极拥抱直播,电商带货、线上教学、企业培训等各种直播场景大范围普及,“X+直播”成为企业在疫情常态化背景下寻求新增长的首选路径。但伴随着直播井喷式增长并真正意义上深入千家万户,观众对直播的体验及质量的要求也水涨船高,高画质、高帧率、立体声等能力正逐步变为标配。企业也在最初的野蛮投入后慢慢回归理性,开始关注如何用更低的成本为观众带来良好的体验。基于这样的背景,腾讯云云直播对产品做了进一步的升级,开放支持AV1编码格式及直播音视频增强功能,让广大企业用户可以用更低的成本为直播观众带来更极
腾讯云音视频
2022/06/20
2.1K0
云直播开放支持AV1 & 音视频增强功能
这项音视频国际赛事,腾讯云拿到21项第一
在连续多年获得H.265编码最佳之后,腾讯云媒体处理产品MPS今年在MSU比赛的H264、HEVC/AV1赛道,又斩获21项评测第一! 其中,TXAV1/V265编码器在所有分辨率测试中,包揽PSNR、SSIM和VMAF所有客观指标以及主观指标第一。同时,腾讯O264编码器也获得该赛道6项指标第一。 (图以1080P成绩为例) 此外,在云服务转码质量/转码成本这项重要业务评测中,腾讯云媒体处理产品MPS(Media Processing Service)也明显领先于其他参赛厂商。在同等转码成本下,使
腾讯云音视频
2023/04/23
6320
这项音视频国际赛事,腾讯云拿到21项第一
推荐阅读
相关推荐
哔哩哔哩H.265编码器在直播和点播的实践和应用
更多 >
LV.3
这个人很懒,什么都没有留下~
目录
  • 防抖节流
  • 你在工作终于到那些问题,解决方法是什么
  • 数组扁平化
  • instance 如何使用
  • 10 个 Ajax 同时发起请求,全部返回展示结果,并且至多允许三次失败,说出设计思路
  • 函数防抖
  • 为什么需要清除浮动?清除浮动的方式
  • 动态规划求解硬币找零问题
  • 实现函数原型方法
  • 虚拟DOM转换成真实DOM
  • Set 和 Map有什么区别?
  • 说一下for...in 和 for...of的区别?
  • 发布订阅模式(事件总线)
  • PWA使用过吗?serviceWorker的使用原理是啥?
  • 原函数形参不定长(此时 fn.length 为0)
  • 说一下常见的HTTP状态码?说一下状态码是302和304是什么意思?你在项目中出现过么?你是怎么解决的?
  • 说一下常见的git操作
  • Promise.reject
  • Vuex有哪些基本属性?为什么 Vuex 的 mutation 中不能做异步操作?
  • 详细说明 Event loop
    • Node 中的 Event loop
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档