Резюме вопросов и ответов на предварительных интервью 2017 | Техническое эссе Nuggets

Технологии Nuggets призывают к публикации опрос

Добавить Автора
Блог:yeaseonzhang.github.io
Оригинальная ссылка

«Золотые три, серебряные четыре, золотые девять, серебряные десять» используются для описания лучших месяцев для поиска работы. Однако с насыщением отрасли ситуация с занятостью младших и средних специалистов не оптимистична.

Состояние отрасли не поддается контролю, и, конечно, все, что мы можем сделать, это сделать себя более конкурентоспособными.

В этом году я также потратил несколько месяцев на подготовку к интервью и закрепление основ. Настоящим я делюсь темами, которые я обобщил в этом процессе, в надежде помочь студентам, которые ищут работу и готовятся к ней.

CSS

Перечислите различные методы очистки поплавков.

/* 1.添加新元素 */
<div class="outer">
  <div class="div1"></div>
  <div class="div2"></div>
  <div class="div3"></div>
  <div class="clearfix"></div>
</div>
.clearfix {
  clear: both;
}

/* 2.为父元素增加样式 */
.clearfix {
  overflow: auto;
  zoom: 1; // 处理兼容性
}

/* 3.:after 伪元素方法 (作用于父元素) */
.outer {
  zoom: 1;
  &:after {
    display: block;
    height: 0;
    clear: both;
    content: '.';
    visibillity: hidden;
  }
}

граница в один пиксель

использоватьsassграмматика.

/* 定义 */
@mixin border-1px ($color) {
    position: relative;
    &:after {
        display: block;
        position: absolute;
        left: 0;
        bottom: 0;
        width: 100%;
        border-top: 1px solid $color;
        context: '';
    }
}

@media (-webkit-min-device-pixel-radio: 1.5), (min-device-pixel-radio: 1.5) {
    border-1px {
        &:after {
            -webkit-transform: scaleY(0.7);
            transform: scaleY(0.7);
        }
    }
}

@media (-webkit-min-device-pixel-radio: 2), (min-device-pixel-radio: 2) {
    border-1px {
        &:after {
            -webkit-transform: scaleY(0.5);
            transform: scaleY(0.5);
        }
    }
}

/* 使用方式 */
@inclue border-1px(rgba(7, 17, 27, .1));

формаBFC(Контекст форматирования блока) несколькими способами

Полное название BFC — «контекст блочного форматирования», что на китайском языке означает «контекст блочного форматирования». Принцип действия характеристик элемента БТЭ заключается в том, что как бы внутренние подэлементы ни вращались над рекой и морем, опрокидывающиеся облака и дожди не повлияют на внешние элементы.

  • floatдляleft|right
  • overflowдляhidden|auto|scroll
  • displayдляtable-cell|table-caption|inline-block
  • positionдляabsolute|fixed

макет

/* HTML */
<div class="container">
  <div class="left">Left silder</div>
  <div class="content">Main content</div>
</div>

/* CSS */
.container {
  overflow: hidden;
}

.left {
  float: left;
  width: 200px;
  margin-bottom: -9999px;
  padding-bottom: 9999px;
  background-color: #eee;
}

.content {
  margin-left: 200px;
  margin-bottom: -9999px;
  padding-bottom: 9999px;
  background-color: #ccc;
}

.left, .content {
  min-height: 200px;
  height: auto !important;
}

JS

asyncа такжеdeferразница

Асинхронный (асинхронный) скрипт будет выполняться, как только завершится загрузка, в то время как отложенный (defer) скрипт будет ждать, пока HTML будет проанализирован и выполнен в порядке загрузки.

location.replace()а такжеlocation.assign()разница

location.replace()URL не появится в истории

newоператор

  • создает пустой объект иthisПеременная ссылается на объект, а также наследует прототип функции.
  • Свойства и методы добавляются вthisв указанном объекте
  • Вновь созданный объект создаетсяthisссылается и, наконец, неявно возвращаетсяthis

AMD CMD CommonJS

/* AMD是RequireJS对模块化的定义
 * CMD是seaJS对模块化的定义
 * CommonJS是Node对模块化的规范
 **/

/* AMD 依赖关系前置 */
define(['./a', './b'], function (a, b) {
    a.something();
    b.something();
})

/* CMD 按需加载,依赖就近 */
define(function (require, exports, module) {
    var a = require('./a');
    a.something();

    var b = require('./b');
    b.something();
})

Манипуляции с DOM

// 创建节点
createDocumentFragment()
createElement()
createTextNode()

// 添加 移除 替换 插入
appendChild()
removeChild()
replaceChild()
insertBefore()

// 查找
getElementsByTagName()
getElementsByName()
getElementsByClassName()
getElementById()
querySelector()
querySelectorAll()

Несколько способов установки стилей CSS в JS

/* 1.直接设置style属性 */
element.style.height = '100px';

/* 2.直接设置属性 */
element.setAttribute('height', '100px');

/* 3.使用setAttribute设置style属性 */
element.setAttribute('style', 'height: 100px !important');

/* 4.使用setProperty设置属性,通过第三个参数设置important */
element.style.setProperty('height', '300px', 'important');

/* 5.设置cssText */
element.style.cssText += 'height: 100px !important';

предотвратить поведение по умолчанию

function stopDefault( e ) {
    // 阻止默认浏览器动作(W3C)
    if ( e && e.preventDefault ) {
        e.preventDefault();
    } else {
        // IE中阻止函数器默认动作的方式
        window.event.returnValue = false;
    }
    return false;
}

перестань пузыриться

function stopBubble(e) {
    // 如果提供了事件对象,则这是一个非IE浏览器
    if ( e && e.stopPropagation ) {
        // 因此它支持W3C的stopPropagation()方法
        e.stopPropagation();
    } else {
        // 否则,我们需要使用IE的方式来取消事件冒泡
        window.event.cancelBubble = true;
    }
}

Интерактивный процесс Ajax

  • Создайте объект XMLHttpRequest, то есть создайте объект асинхронного вызова.
  • Создайте новый HTTP-запрос и укажите метод HTTP-запроса, URL-адрес и данные аутентификации.
  • Задает функцию, которая отвечает на изменения состояния HTTP-запроса.
  • Отправьте HTTP-запрос.
  • Получите данные, возвращенные асинхронным вызовом.
  • Реализуйте частичное обновление с помощью JavaScript и DOM.

Исследуйте самые обширные вопросы JS-интервью

function Foo() {
    getName = function () { alert(1); }
    return this;
}
Foo.getName = function () { alert(2); }
Foo.prototype.getName = function () { alert(3); }
var getName = function () { alert(4); }
function getName () { alert(5); }

/* 写出输出 */
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

Подробнее см.Вопрос о фронтенд-JS-интервью, который часто презирают

Глубокая и неглубокая копия массива JS

  • sliceвыполнить
var arr = ['old', 1, true, null, undefined];

var new_arr = arr.slice();

new_arr[0] = 'new';

console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]
  • concatвыполнить
var arr = ['old', 1, true, null, undefined];

var new_arr = arr.concat();

new_arr[0] = 'new';

console.log(arr) // ["old", 1, true, null, undefined]
console.log(new_arr) // ["new", 1, true, null, undefined]

Вышеуказанные два метода являются только поверхностными копиями.Если элемент массива является базовым типом, будет скопирована новая копия, но если элемент массива является объектом или массивом, будет скопирована только ссылка (аналогично указателю), и изменение одного повлияет на другое.

var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];

var new_arr = arr.concat();

new_arr[0] = 'new';
new_arr[3][0] = 'new1';

console.log(arr) // ["old", 1, true, ['new1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]
  • JSON.stringifyРеализация глубокой копии массива
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}];

var new_arr = JSON.parse(JSON.stringify(arr));

new_arr[0] = 'new';
new_arr[3][0] = 'new1';

console.log(arr) // ["old", 1, true, ['old1', 'old2'], {old: 1}]
console.log(new_arr) // ["new", 1, true, ['new1', 'old2'], {old: 1}]

Просто и грубо, но проблема в том, что функции нельзя копировать, что делать не рекомендуется.

Затем давайте вручную реализуем глубокие и мелкие копии.

  • мелкая копия
var shallowCopy = function (obj) {
    // 判断是否是数组或者对象
    if (typeof obj !== 'object') {
        return
    }
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}
  • глубокая копия
var deepCopy = function (obj) {
    if (typeof obj !== 'object') {
        return
    }
    var newObj = obj instanceof Array ? [] : {};
    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
        }
    }
    return newObj
}

Дедупликация массива

  • filter + indexOf
function unique (arr) {
    var res = arr.filter(function (item, index, array) {
        return array.indexOf(item) === index;
    })
    return res;
}
  • filter + sort
function unique (arr) {
    return arr.concat().sort().filter(function (item, index, array) {
        return !index || item !== array[index - 1];
    })
}
  • ES6
function uniqu3 (arr) {
    return [... new Set(arr)];
}

Найдите наибольшее значение в массиве

  • reduce
var arr = [6, 4, 1, 8, 2, 11, 3];

function max (prev, next) {
    return Math.max(prev, next)
}

console.log(arr.reduce(max));
  • apply
var arr = [6, 4, 1, 8, 2, 11, 3];

console.log(Math.max.apply(null, arr));
  • ES6
var arr = [6, 4, 1, 8, 2, 11, 3];

function max (arr) {
    return Math.max(...arr);
}

console.log(max(arr));

Как перемешать массив

var arr = [];
for (var i = 0; i < 100; i++) {
    arr[i] = i;
}

arr.sort(function () {
    return 0.5 - Math.random();
});

Выравнивание массива

var arr = [1, [2, [3, 4]]];

function flatten(arr) {

    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }

    return arr;
}

console.log(flatten(arr))

Сортировать

// 冒泡
function bubbleSort2(arr) {
    var len = arr.length;
    for (var i = 0; i <= len - 1; i++) {
        for (var j = 0; j <= len - i; j++) {
            if (arr[j + 1] < arr[j]) {
                var temp;
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
    return arr;
}

// 快速排序
function quickSort(arr) {
    if(arr.length == 0) {
        return [];    // 返回空数组
    }

    var cIndex = Math.floor(arr.length / 2);
    var c = arr.splice(cIndex, 1);
    var l = [];
    var r = [];

    for (var i = 0; i < arr.length; i++) {
        if(arr[i] < c) {
            l.push(arr[i]);
        } else {
            r.push(arr[i]);
        }
    }

    return quickSort(l).concat(c, quickSort(r));
}

форматирование чисел1234567890 -> 1,234,567,890

function formatNum (num) {
    return num.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
var num = '1234567890';
var res = formatNum(num);
console.log(res);

Как перемешать массив

var arr = [];
for (var i = 0; i < 100; i++) {
    arr[i] = i;
}

arr.sort(function () {
    return 0.5 - Math.random();
})

оптимизация хвостового вызова

То есть сохраняется только вызывающий фрейм внутренней функции (только при включении строгого режима он вступит в силу), и только когда внутренние переменные внешней функции перестанут использоваться, будет сохраняться вызывающий фрейм внутренней функции. замените кадр вызова внешней функции. Выполните оптимизацию хвостового вызова.

function factorial(n) {
    if (n === 1) return 1;
    return n * factorial(n-1);
}
factorial(5)

/* 优化尾递归 */
function factorial(n, total) {
    if (n === 1) return total;
    return factorial(n - 1, n * total);
}
factorial(5, 1)

карри

выполнитьadd(1,2)а такжеadd(1)(2)средний выход3

function add () {
    let sum = 0;
    Array.prototype.forEach.call(arguments, function (item, index){
        if (typeof item !== 'number') {
            return false;
        } else {
            sum += item;
        }
    })
    var tmp = function () {
        Array.prototype.forEach.call(arguments, function (item, index){
            if (typeof item !== 'number') {
                return false;
            } else {
               sum += item;
            }
        })
        return tmp;
    }
    tmp.toString = function () {
        return sum
    }
    return tmp;
}
add(1, 2); // 3
add(1)(2); // 3
add(1, 2, 3)(1, 4)(2, 2)(1) // 16

Новые функции ES8

  • Заполнение строки
str.padStart(targetLength [, padString])
str.padEnd(targetLength [, padString])
  • valuesа такжеentriesфункция
Object.values(obj)
Object.entries(obj)
  • getOwnPropertyDescriptorsфункция
Object.getOwnPropertyDescriptors(obj)
  • аргументы функции после запятой
function es8(var1, var2, var3,) {}
  • асинхронная функция
    Зависит отasyncФункция, определяемая ключевым словом, объявляет функцию, которая может выполняться асинхронно, возвращаяAsyncFunctionтип объекта.
fucntion fetchTextByPromise () {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('es8');
        }, 2000);
    });
}
async function sayHello () {
    const externalFetchedText = await fetchTextByPromise();
    console.log(`Hello, ${externalFetchedText}`);
}
sayHello();

оценка типа данных

var class2type = {};

'Boolean Number String Function Array Date RegExp Object Error Null Undefined'.split(' ').map((item, index) => {
    class2type['[object ' + item + ']'] = item.toLowerCase();
})

function type (obj) {
    return typeof obj === 'object' || typeof obj === 'function' ?
        class2type[{}.toString.call(obj)] || 'object' : typeof obj;
}

Стабилизатор

/*
 * func:需要调用的函数
 * wait: 防抖时间
 * immediate:布尔值,是否立即执行
 **/

var debounce = function (func, wait, immediate) {
  var timeout;
  return function () {
    var context = this;
    var args = arguments;

    if (timeout) clearTimeout(timeout);

    if (immediate) {  // 是否立即执行func
      var callNow = !timeout;
      timeout = setTimeout(function () {
        timeout = null;
      }, wait);

      if (callNow) {
        func.apply(context, args);
      }
    } else {
      timeout = setTimeout(function () {
        func.apply(context, args);
      }, wait);
    }
  }
}

простой шаблон строки

var TemplateEngine = function(tpl, data) {
    var re = /<%([^%>]+)?%>/g, match;
    while(match = re.exec(tpl)) {
        tpl = tpl.replace(match[0], data[match[1]])
    }
    return tpl;
}

var template = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';
console.log(TemplateEngine(template, {
    name: "Yeaseon",
    age: 24
}));

// '<p>Hello, my name is Yeaseon. I\'m 24 years old.</p>';

apply,callа такжеbind

  • applyа такжеcall

В строгом режиме, если функция вызывается без указания объекта среды, это значение не будет преобразовано в окно. Если вы явно не добавите функцию к объекту или не вызовете apply() или call(), это значение будет неопределенным.

В нестрогом режиме, когда первый параметр вызова и применения передается как нулевой или неопределенный, это в теле функции будет указывать на хост-объект по умолчанию, которым является окно в браузерах.

  • apply,callа такжеbindСравнивать
var obj = {
    x: 81
};

var foo = {
    getX: function () {
        return this.x;
    }
}

console.log(foo.getX.bind(obj)());
console.log(foo.getX.apply(obj));
console.log(foo.getX.call(obj));

Это понятно,bindПосле метода есть дополнительная пара круглых скобок. То есть, когда вы хотите изменить контекст и выполнить немедленно, но выполняется обратный вызов (в основном используется для функций прослушивателя событий), используйтеbind()метод, в то время какapply/callФункция выполняется немедленно.

  • Определите метод журнала, который может проксировать метод console.log.
function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2
  • Добавьте префикс «(приложение)» к каждому сообщению журнала, например:
log("hello world");    //(app)hello world
function log(){
  var args = Array.prototype.slice.call(arguments);
  args.unshift('(app)');
  console.log.apply(console, args);
};
  • applyвыполнитьbind
function bind (fn, context) {
    return function () {
        return fn.apply(context, argument);
    }
}

создать объект

  • Заводская выкройка
function createPerson(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    };
    return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
  • Шаблон конструктора
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        alert(this.name);
    };
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
  • режим прототипа
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
    alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
  • Конструктор + шаблон прототипа
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];
}
Person.prototype = {
    constructor : Person,
    sayName : function(){
        alert(this.name);
    }
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true

JS реализует JQueryextend()метод

function extend() {
    // 默认不进行深拷贝
    var deep = false;
    var name, options, src, copy, clone, copyIsArray;
    var length = arguments.length;
    // 记录要复制的对象的下标
    var i = 1;
    // 第一个参数不传布尔值的情况下,target 默认是第一个参数
    var target = arguments[0] || {};
    // 如果第一个参数是布尔值,第二个参数是 target
    if (typeof target == 'boolean') {
        deep = target;
        target = arguments[i] || {};
        i++;
    }
    // 如果target不是对象,我们是无法进行复制的,所以设为 {}
    if (typeof target !== "object" && !isFunction(target)) {
        target = {};
    }

    // 循环遍历要复制的对象们
    for (; i < length; i++) {
        // 获取当前对象
        options = arguments[i];
        // 要求不能为空 避免 extend(a,,b) 这种情况
        if (options != null) {
            for (name in options) {
                // 目标属性值
                src = target[name];
                // 要复制的对象的属性值
                copy = options[name];

                // 解决循环引用
                if (target === copy) {
                    continue;
                }

                // 要递归的对象必须是 plainObject 或者数组
                if (deep && copy && (isPlainObject(copy) ||
                        (copyIsArray = Array.isArray(copy)))) {
                    // 要复制的对象属性值类型需要与目标属性值相同
                    if (copyIsArray) {
                        copyIsArray = false;
                        clone = src && Array.isArray(src) ? src : [];

                    } else {
                        clone = src && isPlainObject(src) ? src : {};
                    }

                    target[name] = extend(deep, clone, copy);

                } else if (copy !== undefined) {
                    target[name] = copy;
                }
            }
        }
    }

    return target;
};

Пользовательские события (через шаблон наблюдателя)

function EventTarget () {
    this.handlers = {};
}

EventTarget.prototype = {
    constructor: EventTarget,
    addHandler: function (type, handler) {
        if (typeof this.handlers[type] == 'undefined') {
            this.handlers[type] = [];
        }
        this.handlers[type].push(handler)
    },
    fire: function (event) {
        if (!event.target) {
            event.target = this;
        }
        if (this.handlers[event.type] instanceof Array) {
            var handlers = this.handlers[event.type];
            for (var i = 0, len = handlers.length; i < len; i++) {
                handlers[i](event);
            }
        }
    },
    removeHandler: function (type, handler) {
        if (this.handlers[type] instanceof Array) {
            var handlers = this.handlers[type];
            for (var i = 0, len = handlers.length; i < len; i++) {
                if (handlers[i] === handler) {
                    break;
                }
            }
            handlers.splice(i, 1);
        }
    }
}

Безопасность

Несколько методов междоменного

  1. Основной домен - тот же кросс-домен
document.domain
  1. window.postMessage

  2. JSONPМеждоменный (поддерживается толькоGET)

function todo(data){
  console.log('The author is: '+ data.name);
}

var script = document.createElement('script');
/* 向服务器www.yeaseonzhang.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字。 */
script.src = 'http://www.yeaseonzhang.com/author?callback=todo';
document.body.appendChild(script);
/* 服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 */
todo({"name": "fewjq"});
/* 由于<script>元素请求的脚本,直接作为代码运行。这时,只要浏览器定义了todo函数,该函数就会立即调用。作为参数的JSON数据被视为JavaScript对象。*/
  1. websocketперекрестный домен

XSS и CSRF

представление

CSS-оптимизация

  • Подходящее время для вызова CSS
  • Используйте теги медиа-запросов<link>, выборочная загрузка
  • уменьшить количество файлов css
  • Сжать css-код

оказывать