Ionic 3 Как использовать NavController # setRoot () в обещании Ionic Storage [duplicate]

Я отвечу ужасным, нарисованным рукой комиком. Второе изображение является причиной того, что result является undefined в вашем примере кода.

339
задан hippietrail 20 April 2015 в 09:04
поделиться

7 ответов

В дополнение к большим ответам до сих пор я хотел бы представить совершенно другую причину, по которой функции стрелок в определенном смысле существенно лучше, чем «обычные» функции JavaScript. Для обсуждения, давайте временно предположим, что мы используем проверку типа TypeScript или «Flow» Facebook. Рассмотрим следующий игрушечный модуль, который является действительным кодом ECMAScript 6 плюс плюс аннотации типа потока: (я буду включать нетипный код, который в конечном итоге будет получен из Babel в конце этого ответа, поэтому он может быть запущен.)

export class C {
  n : number;
  f1: number => number; 
  f2: number => number;

  constructor(){
    this.n = 42;
    this.f1 = (x:number) => x + this.n;
    this.f2 = function (x:number) { return  x + this.n;};
  }
}

Теперь посмотрим, что произойдет, когда мы используем класс C из другого модуля, например:

let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1: number = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2: number = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!

Как вы можете видеть, ошибка проверки типа здесь: f2 должен был возвратить число, но он вернул строку!

Хуже того, кажется, что нет мыслимой проверки типа может обрабатывать обычные (не стрелочные) функции JavaScript, потому что «это» из f2 не встречается в списке аргументов f2, поэтому требуется type для «this» не может быть добавлен как аннотация к f2.

Эта проблема также затрагивает людей, которые не используют контролеры типов? Я так думаю, потому что даже когда у нас нет статических типов, мы думаем, что они там. («Первые параметры должны быть числом, второе - строкой» и т. Д.). Скрытое «это» действие, которое может или не может быть использовано в теле функции, делает нашу умственную бухгалтерию более сложной.

Вот текущая нетипизированная версия, которая будет вызываться Babel:

class C {
    constructor() {
        this.n = 42;
        this.f1 = x => x + this.n;
        this.f2 = function (x) { return x + this.n; };
    }
}

let o = { f1: new C().f1, f2: new C().f2, n: "foo" };
let n1 = o.f1(1); // n1 = 43
console.log(n1 === 43); // true
let n2 = o.f2(1); // n2 = "1foo"
console.log(n2 === "1foo"); // true, not a string!

5
ответ дан Carsten Führmann 24 August 2018 в 22:56
поделиться
71
ответ дан Jackson 24 August 2018 в 22:56
поделиться
271
ответ дан lyschoening 24 August 2018 в 22:56
поделиться

Функции стрелок - наиболее широко используемая функция ES6 до сих пор ...

Использование: все функции ES5 должны быть заменены функциями стрелок ES6, за исключением следующих сценариев:

Функции стрелок НЕ должны использоваться:

  1. Когда мы хотим, чтобы функция hoisting как функции стрелок была анонимной.
  2. Когда мы хотим использовать this / arguments в функции, поскольку функции стрелки не имеют this / arguments, они зависят от их внешнего контекста.
  3. Когда мы хотим использовать именованную функцию, поскольку функции стрелок анонимны.
  4. Когда мы хотим использовать функцию как constructor, поскольку функции стрелки не имеют своих this.
  5. Когда мы хотим добавить функцию как свойство в объектный литерал и использовать в ней объект, поскольку мы не можем получить доступ к this (который должен быть самим объектом).

Давайте рассмотрим некоторые из вариантов функций стрелок, которые лучше понять:

Вариант 1: Когда мы хотим передать более одного аргумента функции и вернуть некоторые

Версия ES5 :

var multiply = function (a,b) {
    return a*b;
};
console.log(multiply(5,6)); //30

Версия ES6 :

var multiplyArrow = (a,b) => a*b;
console.log(multiplyArrow(5,6)); //30

Примечание: ключевое слово function НЕ требуется. => требуется. {} являются необязательными, когда мы не предоставляем {} return неявно добавляется JavaScript, и когда мы предоставляем {}, нам нужно добавить return, если нам это нужно.

Вариант 2: Если мы хотим передать ТОЛЬКО один аргумент функции и вернуть некоторое значение из него.

Версия ES5 :

var double = function(a) {
    return a*2;
};
console.log(double(2)); //4

Версия ES6 :

var doubleArrow  = a => a*2;
console.log(doubleArrow(2)); //4

Примечание: при передаче только одного аргумента мы можем опустить скобки ().

Вариант 3: когда мы НЕ хотим передавать какие-либо аргумент функции и НЕ хотите возвращать какое-либо значение.

Версия ES5 :

var sayHello = function() {
    console.log("Hello");
};
sayHello(); //Hello

Версия ES6 :

var sayHelloArrow = () => {console.log("sayHelloArrow");}
sayHelloArrow(); //sayHelloArrow

Вариант 4: Если мы хотим явно вернуться из функций стрелок.

Версия ES6 :

var increment = x => {
  return x + 1;
};
console.log(increment(1)); //2

Вариант 5: Когда мы хотим вернуть объект из функций стрелок.

Версия ES6 :

var returnObject = () => ({a:5});
console.log(returnObject());

Примечание: нам нужно обернуть объект в скобки (), в противном случае JavaScript не может различать блок и объект.

Вариант 6: Arro w не имеют arguments (массив, такой как объект), они зависят от внешнего контекста для arguments.

Версия ES6 :

function foo() {
  var abc = i => arguments[0];
  console.log(abc(1));
};    
foo(2); // 2

Примечание: foo - это функция ES5 с массивом arguments, подобным объекту, и переданный ему аргумент 2, поэтому для foo для arguments[0] установлено значение arguments[0].

abc - это функция стрелок ES6, так как у нее нет ее arguments, поэтому она выводит arguments[0] в foo, это внешний контекст.

Вариант 7: Функции стрелки НЕ имеют this, они зависят от внешнего контекста для this

Версия ES5 :

var obj5 = {
  greet: "Hi, Welcome ",
  greetUser : function(user) {
        setTimeout(function(){
        console.log(this.greet + ": " +  user); // "this" here is undefined.
        });
     }
};

obj5.greetUser("Katty"); //undefined: Katty

Примечание. Обратный вызов, переданный setTimeout, является ES5 и имеет свой собственный this, который не определен в среде use-strict, поэтому мы получаем выход:

undefined: Katty

Версия ES6 :

var obj6 = {
  greet: "Hi, Welcome ",
  greetUser : function(user) {
    setTimeout(() => console.log(this.greet + ": " +  user)); 
      // this here refers to outer context
   }
};

obj6.greetUser("Katty"); //Hi, Welcome: Katty

Примечание. Обратный вызов, переданный в setTimeout, является функцией стрелок ES6, и у него нет своего this, поэтому он берет его из внешнего контекста, который является greetUser, который имеет this, который является obj6, следовательно мы получаем выход:

Hi, Welcome: Katty

Разное: мы не можем использовать функцию new со стрелками. Функции стрелки не имеют свойства prototype. У нас нет привязки this, когда функция стрелки вызывается через apply или call.

11
ответ дан Manishz90 24 August 2018 в 22:56
поделиться

Функции стрелок были созданы для упрощения функции scope и решения ключевого слова this, упростив ее. Они используют синтаксис =>, который выглядит как стрелка.

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

Давайте посмотрим на существующий синтаксис ES5. Если ключевое слово this находилось внутри метода объекта (функция который принадлежит объекту), к чему это относится?

var Actor = {
  name: 'RajiniKanth',
  getName: function() {
     console.log(this.name);
  }
};
Actor.getName();

Вышеприведенный фрагмент ссылается на object и печатает имя "RajiniKanth". Давайте рассмотрим нижеприведенный фрагмент и посмотрим, что здесь будет здесь.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach(function(movie) {
     alert(this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

. А теперь, если ключевое слово this находилось внутри method’s function?

Здесь это будет означать window object, чем inner function, как его выпавшее из scope. Поскольку this всегда ссылается на владельца функции, в которой он находится, для этого случая - поскольку он теперь выходит из области видимости - объект window / global.

Когда он находится внутри object 's метод - владелец function является объектом. Таким образом, это ключевое слово привязано к объекту. Однако, когда он находится внутри функции, как автономной, так и внутри другого метода, она всегда будет ссылаться на объект window/global.

var fn = function(){
  alert(this);
}

fn(); // [object Window]

Есть способы решить эту проблему в нашем ES5 сам, рассмотрим, что перед тем, как погрузиться в функции ES6 arrow, как решить проблему.

Как правило, вы должны создать переменную вне внутренней функции метода. Теперь метод ‘forEach’ получает доступ к this и, следовательно, к свойствам object’s и их значениям.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   var _this = this;
   this.movies.forEach(function(movie) {
     alert(_this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

, используя bind, чтобы прикрепить ключевое слово this, которое ссылается на метод method’s inner function.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach(function(movie) {
     alert(_this.name + " has acted in " + movie);
   }).bind(this);
  }
};

Actor.showMovies();

Теперь с помощью функции стрелки ES6 мы можем более эффективно решить проблему lexical scoping.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  showMovies: function() {
   this.movies.forEach((movie) => {
     alert(this.name + " has acted in " + movie);
   });
  }
};

Actor.showMovies();

Arrow functions больше похожи на операторы функций, за исключением того, что они bind это parent scope. Если аргумент arrow function is in top scope, this будет ссылаться на window/global scope, тогда как функция стрелки внутри регулярной функции будет иметь свой этот аргумент так же, как и внешнюю функцию.

С функциями arrow this привязан к закрытию scope во время создания и не может быть изменен. Новый оператор, bind, call и apply не влияют на это.

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
  callback(param);
  }, 1);
};

// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
  doSomething: function () {
  // Here we pass `o` into the async function,
  // expecting it back as `param`
  asyncFunction(o, function (param) {
  // We made a mistake of thinking `this` is
  // the instance of `o`.
  console.log('param === this?', param === this);
  });
  }
};

o.doSomething(); // param === this? false

В приведенном выше примере мы потеряли контроль над этим. Мы можем решить приведенный выше пример, используя переменную ссылку this или используя bind. С ES6 становится легче управлять this в качестве привязки к lexical scoping.

var asyncFunction = (param, callback) => {
  window.setTimeout(() => {
  callback(param);
  }, 1);
};

var o = {
  doSomething: function () {
  // Here we pass `o` into the async function,
  // expecting it back as `param`.
  //
  // Because this arrow function is created within
  // the scope of `doSomething` it is bound to this
  // lexical scope.
  asyncFunction(o, (param) => {
  console.log('param === this?', param === this);
  });
  }
};

o.doSomething(); // param === this? true

Если не функции стрелки

Внутри литерала объекта.

var Actor = {
  name: 'RajiniKanth',
  movies: ['Kabali', 'Sivaji', 'Baba'],
  getName: () => {
     alert(this.name);
  }
};

Actor.getName();

Actor.getName определяется функцией стрелки, но при вызове он оповещает о неопределенности, поскольку this.name является undefined, поскольку контекст остается в window.

Это происходит потому, что функция стрелки связывает контекст лексически с внешним окружением window object ... i.e. Выполнение this.name эквивалентно window.name, которое не определено.

Прототип объекта

Это же правило применяется при определении методов на prototype object. Вместо использования функции-стрелки для определения метода sayCatName, который приводит к некорректному context window:

function Actor(name) {
  this.name = name;
}
Actor.prototype.getName = () => {
  console.log(this === window); // => true
  return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined

Конструкторы Invoke

this в вызове построения - это вновь созданный объект , При выполнении нового Fn () контекст constructor Fn является новым объектом: this instanceof Fn === true.

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

var Message = (text) => {
  this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');

Обратный вызов с динамическим контекстом

Функция Arrow связывает декларацию context статически и не может сделать ее динамической. Присоединение прослушивателей событий к элементам DOM является общей задачей при программировании на стороне клиента. Событие запускает функцию обработчика с этим в качестве целевого элемента.

var button = document.getElementById('myButton');
button.addEventListener('click', () => {
  console.log(this === window); // => true
  this.innerHTML = 'Clicked button';
});

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

Вы должны применить выражение функции, которое позволяет изменить это в зависимости от целевого элемента:

var button = document.getElementById('myButton');
button.addEventListener('click', function() {
  console.log(this === button); // => true
  this.innerHTML = 'Clicked button';
});

Когда пользователь нажимает кнопку, это в функции обработчика является кнопкой. Таким образом, this.innerHTML = 'Clicked button' корректно изменяет текст кнопки, чтобы отразить статус щелчка.

Ссылки: https://rainsoft.io/when-not-to-use-arrow-functions-in-javascript/

31
ответ дан maysi 24 August 2018 в 22:56
поделиться

Простым способом,

var a =20; function a(){this.a=10; console.log(a);} 
//20, since the context here is window.

Другой экземпляр:

var a = 20;
function ex(){
this.a = 10;
function inner(){
console.log(this.a); //can you guess the output of this line.
}
inner();
}
var test = new ex();

Ans: Консоль будет печатать 20.

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

Итак, если мы хотим, чтобы функция inner имела локальный контекст, который является ex, нам нужно привязать контекст к внутренней функции .

Стрелки решают эту проблему, вместо того, чтобы принимать Global context, они берут local context, если они существуют. В given example, он примет значение new ex() как this.

Итак, во всех случаях, когда привязка является явной, Arrows решает проблему по умолчанию.

1
ответ дан Rajendra kumar Vankadari 24 August 2018 в 22:56
поделиться
3
ответ дан zowers 24 August 2018 в 22:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: