[Расширенная фаза 3-5] Углубленный анализ новых принципов и реализации моделирования

JavaScript опрос

Обновление: Спасибо за вашу поддержку. Недавно я бросил сводку данных для всех, чтобы прочитать систему. В будущем будет больше контента и больше оптимизации.Нажмите здесь, чтобы просмотреть

------ Далее идет текст ------

определение

новый операторСоздает экземпляр пользовательского типа объекта или экземпляр встроенного объекта с помощью конструктора. - (из МДН)

взять каштан

function Car(color) {
    this.color = color;
}
Car.prototype.start = function() {
    console.log(this.color + " car start");
}

var car = new Car("black");
car.color; // 访问构造函数里的属性
// black

car.start(); // 访问原型里的属性
// black car start

Как можно заметитьnewСозданный экземпляр имеет следующие 2 характеристики

  • 1. Доступ к свойствам в конструкторе
  • 2. Доступ к свойствам в прототипе

будь осторожен

ES6 новыйsymbolтипа нельзя использоватьnew Symbol(),потому чтоsymbolявляются примитивными типами данных, каждый изSymbol()вернутьsymbolВсе значения уникальны.

Number("123"); // 123
String(123); // "123"
Boolean(123); // true
Symbol(123); // Symbol(123)

new Number("123"); // Number {123}
new String(123); // String {"123"}
new Boolean(true); // Boolean {true}
new Symbol(123); // Symbol is not a constructor

Реализация моделирования

когда кодnew Foo(...)При выполнении происходят следующие вещи:

  1. один унаследовал отFoo.prototypeСоздается новый объект.
  2. вызвать конструктор с указанными аргументамиFoo, и воляthisПривязать к вновь созданному объекту.new FooЭквивалентноnew Foo(), то есть без указания списка параметров,FooПри вызове без аргументов.
  3. Объект, возвращаемый конструктором,newрезультат выражения. Если конструктор явно не возвращает объект, используется объект, созданный на шаге 1.

Первый шаг в симуляции

newявляется ключевым словом и не может быть охвачен напрямую. использовать здесьcreateимитироватьnewЭффект.

newвозвращает новый объект, переданныйobj.__proto__ = Con.prototypeНаследует прототип конструктора, при прохожденииCon.apply(obj, arguments)Вызовите родительский конструктор для реализации наследования и получите свойства конструктора ([Дополнительная фаза 3–3]).

Код реализации выглядит следующим образом

// 第一版
function create() {
	// 创建一个空的对象
    var obj = new Object(),
	// 获得构造函数,arguments中去除第一个参数
    Con = [].shift.call(arguments);
	// 链接到原型,obj 可以访问到构造函数原型中的属性
    obj.__proto__ = Con.prototype;
	// 绑定 this 实现继承,obj 可以访问到构造函数中的属性
    Con.apply(obj, arguments);
	// 返回对象
    return obj;
};

пройти тест

// 测试用例
function Car(color) {
    this.color = color;
}
Car.prototype.start = function() {
    console.log(this.color + " car start");
}

var car = create(Car, "black");
car.color;
// black

car.start();
// black car start

Идеально!

незнакомыйapply / callНажмите, чтобы просмотреть:[Расширенная фаза 3-3] Углубленный анализ принципов вызова и применения, сценариев использования и реализации

незнакомыйнаследоватьНажмите, чтобы просмотреть:Восемь распространенных схем наследования в JavaScript

Имитационная реализация второго шага

Приведенный выше код достиг 80%, теперь продолжаем оптимизировать.

Возвращаемое значение конструктора имеет следующие три ситуации:

  • 1. Вернуть объект
  • 2. Нетreturn, который возвращаетundefined
  • 3. ВозвратundefinedОсновные типы, кроме

Дело 1: возвращает объект

function Car(color, name) {
    this.color = color;
    return {
        name: name
    }
}

var car = new Car("black", "BMW");
car.color;
// undefined

car.name;
// "BMW"

примерcarможно получить только вВернуть свойства в объекте.

Случай 2:нетreturn, который возвращаетundefined

function Car(color, name) {
    this.color = color;
}

var car = new Car("black", "BMW");
car.color;
// black

car.name;
// undefined

примерcarможно получить только всвойства в конструкторе, что прямо противоположно случаю 1.

Случай 3:вернутьundefinedОсновные типы, кроме

function Car(color, name) {
    this.color = color;
    return "new car";
}

var car = new Car("black", "BMW");
car.color;
// black

car.name;
// undefined

примерcarможно получить только всвойства в конструкторе, что является полной противоположностью случая 1, и результат эквивалентен отсутствию возвращаемого значения.

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

Таким образом, код реализации выглядит следующим образом:

// 第二版
function create() {
	// 创建一个空的对象
    var obj = new Object(),
	// 获得构造函数,arguments中去除第一个参数
    Con = [].shift.call(arguments);
	// 链接到原型,obj 可以访问到构造函数原型中的属性
    obj.__proto__ = Con.prototype;
	// 绑定 this 实现继承,obj 可以访问到构造函数中的属性
    var ret = Con.apply(obj, arguments);
	// 优先返回构造函数返回的对象
	return ret instanceof Object ? ret : obj;
};

[Продвинутая фаза 3-4] Решение проблем мышления

Вопрос: Реализовать функцию бесконечного накопления в JSadd, пример следующий:

add(1); // 1
add(1)(2);  // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10 

// 以此类推

выполнить:

function add(a) {
	function sum(b) { // 使用闭包
    	a = a + b; // 累加
    	return sum;
 	}
 	sum.toString = function() { // 重写toString()方法
        return a;
    }
 	return sum; // 返回一个函数
}

add(1); // 1
add(1)(2);  // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10 

Мы знаем, что функция печати вызывается автоматически, когдаtoString()метод, функцияadd(a)возвращать закрытиеsum(b), функцияsum()кумулятивный расчетa = a + b, просто нужно переписатьsum.toString()возвращаемая переменная методаaПросто нормально.

Ссылаться на

Углубленная новая реализация моделирования JavaScript

новый оператор MDN

Символ MDN

Функция javascript add(1)(2)(3)(4) реализует бесконечное накопление