Продвинутое JS-собеседование должно знать несколько моментов

внешний интерфейс JavaScript

Все в Шэньчжэне собирают состояние, чтобы нанять фронтенда ~~~

Наймите фронтенда, наймите фронтенда, наймите фронтенда, добро пожаловать, чтобы отсканировать код, чтобы присоединиться к группе, оставьте свое резюме здесь:

предисловие

За это время я вдруг обнаружил, что многие вещи в JS native были забыты, но некоторые вещи действительно важны, так что буду разбираться еще раз. В основном существует 3 способа определения функций, на которые указывает функция ES5, использование вызова и приложения, 4 общих шаблона проектирования JS, цепочка прототипов, цепочка прототипов и методы наследования (ES5 и ES6).

1. 3 способа определения функций

1.1 Описание функции

//ES5
function getSum(){}
function (){}//匿名函数
//ES6
()=>{}//如果{}内容只有一行{}和return关键字可省,

1.2 Функциональные выражения (функциональные литералы)

//ES5
var sum=function(){}
//ES6
let sum=()=>{}//如果{}内容只有一行{}和return关键字可省,

1.3 Конструктор

var sum=new GetSum(num1,num2)

1.4 Сравнение трех методов

1. Объявления функций предварительно анализируются, и объявления функций имеют более высокий приоритет, чем переменные;
2. Способ использования конструктора Function для определения функции — это функциональное выражение, которое приводит к двойному синтаксическому анализу кода и влияет на производительность. Первый анализирует обычный код JavaScript, второй анализирует строку, переданную в конструктор.

2. 4 типа вызовов функций в ES5

В ES5 указатель this содержимого функции связан с вызывающим методом.

2.1 Режим вызова функции

Включая имя функции () и анонимные вызовы функций, это указывает на окно

 function getSum() {
    console.log(this) //window
 }
 getSum()
 
 (function() {
    console.log(this) //window
 })()
 
 var getSum=function() {
    console.log(this) //window
 }
 getSum()

2.2 Вызов метода

Объект.Имя метода(), это указывает на объект

var objList = {
   name: 'methods',
   getSum: function() {
     console.log(this) //objList对象
   }
}
objList.getSum()

2.3 Вызов конструктора

новое имя конструктора(), это указывает на конструктор

function Person() {
  console.log(this); //指向构造函数Person
}
var personOne = new Person();

2.4 Косвенные вызовы

Для этого используйте вызов и применение. Это первый параметр, соответствующий вызову и применению. Если значение не передано или первое значение равно нулю, это указывает на окно, когда оно не определено.

function foo() {
   console.log(this);
}
foo.apply('我是apply改变的this值');//我是apply改变的this值
foo.call('我是call改变的this值');//我是call改变的this值

3. Вызов функции в ES6

Стрелочные функции нельзя использовать в качестве конструкторов, то есть объект нельзя создать с помощью новой команды, иначе будет выброшена ошибка
this функции стрелки связано с определением и не имеет ничего общего с вызовом
Вызов — это шаблон вызова функции.

(() => {
   console.log(this)//window
})()

let arrowFun = () => {
  console.log(this)//window
}
arrowFun()

let arrowObj = {
  arrFun: function() {
   (() => {
     console.log(this)//arrowObj
   })()
   }
 }
 arrowObj.arrFun();

4.звоните, обращайтесь и связывайтесь

1. IE5 не поддерживает вызов и применение, привязка взята из ES5;
2.call и apply могут вызывать функции, изменять это и реализовывать методы наследования и заимствования других объектов;

4.1 Определение вызова и применения

Вызвать метод, который заменяет один объект другим (этот)
object.call(новый этот объект, аргумент 1, аргумент 2, аргумент 3...)
object.apply(новый этот объект, [параметр 1, параметр 2, параметр 3...])

4.2 позвонить и применить использование

1. Косвенно вызовите функцию и измените это значение области видимости.
2. Методы захвата других объектов

var foo = {
  name:"张三",
  logName:function(){
    console.log(this.name);
  }
}
var bar={
  name:"李四"
};
foo.logName.call(bar);//李四
实质是call改变了foo的this指向为bar,并调用该函数

3. Две функции реализуют наследование

function Animal(name){   
  this.name = name;   
  this.showName = function(){   
    console.log(this.name);   
  }   
}   
function Cat(name){  
  Animal.call(this, name);  
}    
var cat = new Cat("Black Cat");   
cat.showName(); //Black Cat

4. Добавьте методы массива push, pop в массивы классов (arguments и nodeList)

(function(){
  Array.prototype.push.call(arguments,'王五');
  console.log(arguments);//['张三','李四','王五']
})('张三','李四')

5. Объединить массивы

let arr1=[1,2,3]; 
let arr2=[4,5,6]; 
Array.prototype.push.apply(arr1,arr2); //将arr2合并到了arr1中

6. Найдите максимальное значение массива

Math.max.apply(null,arr)

7. Определите тип персонажа

Object.prototype.toString.call({})

4.3 bind

bind — это метод расширения функции.После связывания код повторно связывает указатель this внутри func, метод не будет вызываться и несовместим с IE8.

var name = '李四'
 var foo = {
   name: "张三",
   logName: function(age) {
   console.log(this.name, age);
   }
 }
 var fooNew = foo.logName;
 var fooNewBind = foo.logName.bind(foo);
 fooNew(10)//李四,10
 fooNewBind(11)//张三,11  因为bind改变了fooNewBind里面的this指向

5. Четыре распространенных шаблона проектирования в JS

5.1 Заводской образец

Простой фабричный шаблон можно понимать как решение нескольких схожих задач;

function CreatePerson(name,age,sex) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age);  // 28
console.log(p1.sex);  // 男
console.log(p1.sayName()); // longen

console.log(p2.name);  // tugenhua
console.log(p2.age);   // 27
console.log(p2.sex);   // 女
console.log(p2.sayName()); // tugenhua  

5.2 Одноэлементный шаблон

Может быть создан только один раз (конструктор добавляет свойства и методы к экземпляру)

// 单体模式
var Singleton = function(name){
    this.name = name;
};
Singleton.prototype.getName = function(){
    return this.name;
}
// 获取实例对象
var getInstance = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {//相当于一个一次性阀门,只能实例化一次
            instance = new Singleton(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例,所以a===b
var a = getInstance("aa");
var b = getInstance("bb");  

5.3 Режим песочницы

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

let sandboxModel=(function(){
    function sayName(){};
    function sayAge(){};
    return{
        sayName:sayName,
        sayAge:sayAge
    }
})()

5.4 Модель подписки издателя

Например, если мы подписаны на определенный публичный аккаунт, то он будет подталкивать вам новые новости, соответствующие ему,

//发布者与订阅模式
    var shoeObj = {}; // 定义发布者
    shoeObj.list = []; // 缓存列表 存放订阅者回调函数

    // 增加订阅者
    shoeObj.listen = function(fn) {
        shoeObj.list.push(fn); // 订阅消息添加到缓存列表
    }

    // 发布消息
    shoeObj.trigger = function() {
            for (var i = 0, fn; fn = this.list[i++];) {
                fn.apply(this, arguments);//第一个参数只是改变fn的this,
            }
        }
     // 小红订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("颜色是:" + color);
        console.log("尺码是:" + size);
    });

    // 小花订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("再次打印颜色是:" + color);
        console.log("再次打印尺码是:" + size);
    });
    shoeObj.trigger("红色", 40);
    shoeObj.trigger("黑色", 42);  

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

Для получения дополнительных шаблонов дизайна, пожалуйста, нажмите:Подробное объяснение общих шаблонов проектирования в Javascript.

6. Цепочка прототипов

6.1 Определения

Цепочка свойств наследования объекта

6.2 Конструктор, связь между экземпляром и объектом-прототипом

图片描述
Описание изображения

var Person = function (name) { this.name = name; }//person是构造函数
var o3personTwo = new Person('personTwo')//personTwo是实例

图片描述
Описание изображения

Объекты-прототипы имеют свойство конструктора по умолчанию, указывающее на конструктор.

6.3 Как создать экземпляр

1. Буквальный

let obj={'name':'张三'}

2. Создание конструктора объектов

let Obj=new Object()
Obj.name='张三'

3. Используйте фабричный шаблон для создания объектов

function createPerson(name){
 var o = new Object();
 o.name = name;
 };
 return o; 
}
var person1 = createPerson('张三');

4. Используйте конструктор для создания объектов

function Person(name){
 this.name = name;
}
var person1 = new Person('张三');

6.4 Новый оператор

1. Создайте новый объект;
2. это указывает на конструктор;
3. Конструктор вернулся, заменив объект из New, если нет, то выходящий объект.
4. Вручную инкапсулировать новый оператор

var new2 = function (func) {
    var o = Object.create(func.prototype);    //创建对象
    var k = func.call(o);             //改变this指向,把结果付给k
    if (typeof k === 'object') {         //判断k的类型是不是对象
        return k;                  //是,返回k
    } else {
        return o;                  //不是返回返回构造函数的执行结果
    }
}  

Подробнее:Подробно о цепочке прототипов JavaScript

6.5 Цепочка прототипов объектов

图片描述
Описание изображения

7. Способ наследования

JS - это слабо напечатанный динамический язык, инкапсуляция и наследство - это две основные характеристики

7.1 наследование цепочки протоколов

Использовать экземпляр родительского класса в качестве прототипа дочернего класса
1. Реализация кода
Определите родительский класс:

// 定义一个动物类
function Animal (name) {
  // 属性
  this.name = name || 'Animal';
  // 实例方法
  this.sleep = function(){
    console.log(this.name + '正在睡觉!');
  }
}
// 原型方法
Animal.prototype.eat = function(food) {
  console.log(this.name + '正在吃:' + food);
};

Подкласс:

function Cat(){ 
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

// Test Code
var cat = new Cat();
console.log(cat.name);//cat
console.log(cat.eat('fish'));//cat正在吃:fish  undefined
console.log(cat.sleep());//cat正在睡觉! undefined
console.log(cat instanceof Animal); //true 
console.log(cat instanceof Cat); //true

2. Преимущества и недостатки
Просто и легко реализовать, но если вы хотите добавить свойства и методы к подклассам, вы должны выполнить их после операторов, таких как new Animal(), которые не могут обеспечить множественное наследование.

7.2 Конструктивное наследование

Суть в том, чтобы использовать вызов для изменения этой точки в Cat
1. Реализация кода
Подкласс:

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}

2. Преимущества и недостатки
Множественное наследование может быть достигнуто, но свойства/методы прототипа не могут быть унаследованы

7.3 Наследование экземпляра

Добавьте новые свойства в экземпляр родительского класса и верните его как экземпляр дочернего класса.
1. Реализация кода
Подкласс

function Cat(name){
  var instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

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

7.4 Наследование копирования

Скопируйте свойства и методы родительского класса в детский класс
1. Подкласс:

function Cat(name){
  var animal = new Animal();
  for(var p in animal){
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

2. Преимущества и недостатки
Поддерживает множественное наследование, но неэффективно и занимает память

7.5 Композиционное наследование

Вызывая структуру родительского класса, наследуйте свойства родительского класса и сохраняйте преимущества передачи параметров, а затем реализуйте повторное использование функций, используя экземпляр родительского класса в качестве прототипа дочернего класса.
1. Подкласс:

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;

7.6 Наследование паразитарного состава

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();

7.7 ES6 расширяет наследование

Механизм наследования ES6 заключается в том, чтобы сначала создать объект экземпляра this родительского класса (поэтому сначала должен быть вызван суперметод), а затем использовать конструктор подкласса для его изменения.Ссылка Описание

class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    return this.color + ' ' + super.toString(); // 调用父类的toString()
  }
}   

Для получения более подробной информации, пожалуйста, нажмите:Реализация наследования JS

использованная литература:

www.cnblogs.com/tugen...
www.cnblogs.com/humin...
www.cnblogs.com/cheng...
www.cnblogs.com/cheng...