Вопросы, связанные с JS, на фронтенд-интервью (2)

внешний интерфейс JavaScript опрос ECMAScript 6

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

Все ли объекты в JavaScript?

«Все есть объект!» Все были убеждены. На самом деле это не так.В нем много языковых ловушек.Лучше не хвастаться перед другими,что все есть объект.

тип данных

JavaScript — это слабо типизированный или динамический язык. Это означает, что вам не нужно заранее объявлять тип переменной, тип будет автоматически определен во время выполнения программы. Это также означает, что вы можете использовать одну и ту же переменную для хранения разных типов данных.Последний стандарт ECMAScript определяет 7 типов данных:

базовый тип

  • Boolean
  • Null
  • Undefined
  • Number
  • String
  • Символ (новое определение в ECMAScript 6)

тип объекта

  • Object

Типы объектов охватывают множество ссылочных типов, и все, что не является примитивным типом, является типом объекта. Например, Функция (Функция — это обычный объект с функциями, которые можно вызывать), поэтому я не буду здесь вдаваться в подробности.

По этой классификации видно, что «не все связано».

Мы можем различать два типа двумя способами:

разница

изменчивость

Базовые типы: неизменяемые типы, не могут добавлять свойства, даже если вы добавите свойства, синтаксический анализатор не сможет их прочитать на следующем шаге;

var cat = "cat";
cat.color = "black";
cat.color // undefined

Тип объекта: изменяемый тип, поддерживающий добавление и удаление свойств.

сравнить и пройти

Основные типы: сравнение по значению, передача по значению;
Типы объектов: сравнение по ссылке, передача по ссылке.

// 基本类型
var cat = "tom";
var dog = "tom";
cat === dog // true
//对象类型
var cat = {name:"tom"};
var dog = {name:"tom"};
cat === dog //false

Мы говорим о сравнении объектов по ссылке: то, имеют ли два объекта одинаковое значение, зависит от того, указывают ли они на один и тот же базовый объект __Дэвид Фланаган

Поэтому мы меняем его на это:

var cat = {name:"tom"}
var dog = cat;
b.name = "Haba"

dog === cat // true

Как определить тип объекта? Или как определить, что данные являются типом массива?

Для определения типа объекта настоятельно рекомендуется использовать метод Object.prototype.toString, так как это единственный надежный способ. Мы используем метод Object.prototype.toString:

Object.prototype.toString.call([])    // "[object Array]"
Object.prototype.toString.call({})    // "[object Object]"
Object.prototype.toString.call(2)    // "[object Number]"

Почему я не могу использовать typeOf?

typeof полезен только при обнаружении базовых типов, в ссылочных типах (кроме Function) он возвращает объекты, а typeof null === "object".

Краткий разговор об объектной ориентации

«Объектно-ориентированное программирование (ООП)» — современная парадигма программирования, основная идея которой состоит в том, чтобы абстрагировать различные сложные отношения в реальном мире в объекты, а затем разделить труд и сотрудничество между объектами для завершения имитации реального мира.

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

Два типичных объектно-ориентированных понятия: класс и экземпляр

  • класс: шаблон типа объекта
  • Экземпляр: объект, созданный из класса

К сожалению, в JavaScript нет концепции классов, но он использует конструкторы в качестве шаблонов для объектов.

//构造函数
var Pet = function (name, language) {
    this.name = name;
    this.say = function () {
        console.log(language);
    }
}
// new 关键字生成对象 有关new操作符我们在后面会讲到。
var cat = new Pet('tom', 'meow');
cat.name // tom
cat.say() // meow

Что делает new для создания объекта?

new используется для создания нового объекта, например:

function Pet () {}
var tom = new Pet();

новый делает следующее:

  • Создайте пустой объект, ссылайтесь на объект с этой переменной и наследуйте прототип функции.
  • К этому эталонному объекту добавляются свойства и методы.
  • На вновь созданный объект ссылается this и, наконец, неявно возвращает this
    Процесс моделирования:
    function newObj(Fun,arguments) {
        var o = {};
        if (Fun && typeof Fun === "function") {
            o.__proto__ = Fun.prototype;
            Fun.apply(o, arguments);
            return o;
        }
    }
    

Здесь следует отметить, что внутри конструктора есть оператор return. Если за return следует объект, новая команда возвращает объект, указанный в return; в противном случае она возвращает его напрямую, независимо от оператора return.

var Pet = function (name) {
    this.name = name;
    return {notInstance:"blabla"}
}
var cat = new Pet('tom');
cat.name // undefined
cat.notInstance // blabla

Проработать цепочку прототипов? Как js реализует наследование?

Конструктор, упомянутый выше, свойства и методы экземпляра объекта реализованы внутри конструктора. У такого конструктора есть недостаток:

var cat1 = new Pet('tom', 'meow');
var cat2 = new pet('jery', 'meow');

cat1.say === cat2.say // false

Сгенерируйте двух кошек с одинаковым мяуканьем, но у них разный метод say, то есть новый метод say генерируется каждый раз при создании нового объекта. Все методы say ведут себя одинаково и полностью доступны для совместного использования.
Прототип JavaScript (прототип) позволяет нам добиться совместного использования.

Цепь прототипа?

JavaScript может использовать конструктор (конструктор) для создания нового объекта, каждый конструктор имеет свойство прототипа, и каждый объект, созданный этим конструктором, имеет внутреннюю частную ссылку на прототип конструктора (прототип) (proto), и поскольку этот прототип является объект, у него также есть свой собственный прототип, поэтому на один уровень выше, пока прототип не станет нулевым, что составляет цепочку прототипов.

Как работает цепочка прототипов:

function getProperty(obj, prop) {
    if (obj.hasOwnProperty(prop)) //首先查找自身属性,如果有则直接返回
        return obj[prop]
    else if (obj.__proto__ !== null)
        return getProperty(obj.__proto__, prop) //如何不是私有属性,就在原型链上一步步向上查找,直到找到,如果找不到就返回undefind
    else
        return undefined
}

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

Object.getPrototypeOf(Object.prototype)
// null

Цепочка прототипов показывает процесс поиска объектом своих свойств: сначала ищите сам объект -> если не найдете, то ищите прототип объекта -> если все равно не можете найти, ищите для прототипа прототипа -> до тех пор, пока Object.prototype не найдет меньше, чем -> вернет undefined. (Немедленно вернитесь, если найдено в этом поиске).

свойство конструктора

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

var Pet = function (name) {
    this.name = name;
}
// 尽量避免这么写,因为会把construct属性覆盖掉。
Pet.prototype = {
    say: function () {
        console.log('meow');
    }
}

// 如果我们覆盖了constructor属性要记得将他指回来。
Pet.prototype.constructor = Pet;

Разница между атрибутом __proto__ и атрибутом прототипа

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

Вот два момента:

  • Конструкторы получают доступ к объектам-прототипам через свойство прототипа.
  • Объекты-экземпляры получают доступ к объектам-прототипам через внутреннее свойство [[prototype]], а браузеры реализуют свойство __proto__ для объектов-экземпляров для доступа к объектам-прототипам.

Когда Object является конструктором, он является экземпляром объекта Function; когда Function является конструктором, Function.prototype является объектом, тогда он является экземпляром объекта Object.

Давайте посмотрим на тему:

var F = function(){};
Object.prototype.a = function(){};
Function.prototype.b = function(){};
var f = new F();
// f 能取到a,b吗?原理是什么?

По отношению цепочки прототипов:

f — объект-экземпляр F и его цепочка прототипов:

f.__proto__ -> [F prototype].__proto__ -> [Object prototype].__proto__ -> null

F — это конструктор, экземпляр Function и его цепочка прототипов:

F.__proto__ -> [Function prototype].__proto__ -> [Object prototype].__proto__ -> null

Следовательно, только F может получить доступ к прототипу Function, и ответ будет таким: «f может получить доступ только к a, а F может получить доступ к a и b».

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

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

function Animal(){
    this.super = 'animal';
}
function Cat(name) {
    this.name = name;
    this.food = 'fish';
}
Cat.prototype = new Animal(); // Cat 继承了Animal
Cat.prototype.getFood = function () {
    return this.food;
}

Существует проблема с конструктором, указывающим на вышеуказанный метод:

var cat = new Cat('tom');
cat.name // tom
cat.super // animal
cat.getFood() // fish
//but
cat.constructor === Cat //false
cat.constructor === Animal //true

Конструктор cat указывает не на Cat, а на родительский класс Animal. Нам нужно это починить:

function Cat(name){
    this.name = name;
    this.food = 'fish';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
Cat.prototype.getFood = function () {
    return this.food;
}

Что ж, вышеприведенное реализует простое прототипное наследование.

Суммировать

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

Что касается объектной ориентации, я хотел бы сказать, что js «почти все является объектом», из-за существования цепочки прототипов мы можем добиться наследования, аналогичного другим языкам.

плюсПредыдущая статья, В этих двух статьях рассмотрено большинство вопросов, связанных с js, а в следующей статье может быть объяснена однопоточная модель и связанные с ней таймеры. Это сложный момент, и я понял это, прочитав много информации. этот разСерия интервьюОн в основном нацелен на "средний и продвинутый интерфейс", который также является продвинутым уровнем. Не расстраивайтесь, все, придет день, когда все прояснится.

"Женская волейбольная команда выиграла чемпионат. В этом году кажется, что много раз я обращала внимание на идеальный финал. Я очень рада за них. Я также надеюсь, что в моем будущем также будет идеальный финал. Спокойной ночи.

Пожалуйста, следите за моей колонкой"Фронтальный продуктовый магазин"

Справочная статья