0611-JS 笔记

回调

使用 this 对象的方法作为回调函数时的问题

如果回调函数被传递给一个全局函数,this 对象指向全局 window 对象(在浏览器中)

var clientData = {
  id: 094545,
  fullName: 'Not Set',
  setUserName: function(firstName, lastName) {
    // 这指向了对象中的 fullName 属性
    this.fullName = firstName + ' ' + lastName;
  }
};

function getUserInput(firstName, lastName, callback) {
  // 在这做些什么来确认 firstName/lastName

  // 现在存储 names
  callback(firstName, lastName);
}

getUserInput('Wang', 'RiYu', clientData.setUserName);

console.log(clientData.fullName); //Not Set
console.log(fullName); //Wang RiYu

当 clientData.setUsername 被执行时,this.fullName 并没有设置 clientData 对象中的 fullName 属性。

相反,它将设置 window 对象中的 fullName 属性,因为 getUserInput 是一个全局函数。

这是因为全局函数中的 this 对象指向 window 对象。

修复上面出现的问题

使用 Call 和 Apply 函数保存 this

  • call 接收的第一个参数为被用来在函数内部当做 this 的对象,传递给函数的参数被挨个传递(当然使用逗号分开)

  • apply 函数的第一个参数也是在函数内部作为 this 的对象,然而最后一个参数确是传递给函数的值的数组

function getUserInput(firstName, lastName, callback. callbackObj){
  // 在这里做些什么来确认名字

  callback.apply(callbackObj, [firstName, lastName]);
}

使用 Apply 函数正确设置了 this 对象,我们现在正确的执行了 callback 并在 clientData 对象中正确设置了 fullName 属性

// 我们将 clientData.setUserName 方法和 clientData 对象作为参数
//clientData 对象会被 Apply 方法使用来设置 this 对象

getUserName('Barack', 'Obama', clientData.setUserName, clientData);

//clientData 中的 fullName 属性被正确的设置

console.log(clientUser.fullName);

回调函数特点

  • 回调函数是一段可执行的代码段,它作为一个参数传递给其他的代码,其作用是在需要的时候方便调用这段(回调函数)代码
  • 不会立刻执行, 调用 add 时才会执行 print
  • 回调函数是一个闭包,也就是说它能访问到其外层定义的变量
function add(num1, num2, callback) {
  var sum = num1 + num2;
  callback(sum);
}

function print(num) {
  console.log(num);
}

add(1, 2, print);

// 在执行回调函数前最好确认其是一个函数
function add(num1, num2, callback) {
  var sum = num1 + num2;
  if (typeof callback === 'function') {
    callback(sum);
  }
}

注意在回调函数调用时 this 的执行上下文并不是回调函数定义时的那个上下文,而是调用它的函数所在的上下文

var obj = {
  sum: 0,
  add: function(num1, num2) {
    this.sum = num1 + num2;
    console.log(this.sum);
  }
};

function add(num1, num2, callback) {
  callback(num1, num2);
}

add(1, 2, obj.add);
console.log(obj.sum); //0
console.log(sum);

上述代码调用回调函数的时候是在全局环境下,因此 this 指向的是 window,所以 sum 的值是赋值给 windows 的

function fn(arg1, arg2, callback) {
  var rand = Math.random();
  console.log(rand);
  var num = Math.floor(rand * (arg2 - arg1) + arg1);
  callback(num);
}

fn(10, 20, function(num) {
  console.log('Callback called! Num:' + num);
});
// 结果为 10 和 20 之间的随机数

var clientData = {
  id: 094545,
  fullName: 'Not Set',
  setUserName: function(firstName, lastName) {
    // 这指向了对象中的 fullName 属性
    this.fullName = firstName + ' ' + lastName;
  }
};

function getUserInput(firstName, lastName, callback) {
  // 在这做些什么来确认 firstName/lastName

  // 现在存储 names
  callback(firstName, lastName);
}

getUserInput('Wang', 'RiYu', clientData.setUserName);

console.log(clientData.fullName); //Not Set
console.log(fullName); // Wang RiYu

闭包

闭包作用,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

function add() {
  var counter = 0;
  function plus() {
    counter += 1;
  }
  plus();
  console.log(counter);
}

add(); // 1
add(); // 1
add(); // 1

/*-------------------------------------------*/

var add = (function() {
  var counter = 0;
  return function() {
    console.log((counter += 1));
  };
})();

add(); // 1
add(); // 2
add(); // 3
function makeFunc1(x) {
  return function() {
    return x++;
  };
}
var a = [makeFunc1(0), makeFunc1(1), makeFunc1(2)];
console.log(a[0]()); // 0
console.log(a[1]()); // 1
console.log(a[2]()); // 2

/*-------------------------------*/

function makeFunc2(x) {
  function foo() {
    console.log(x++);
  }
  foo();
}
var b = [makeFunc2(0), makeFunc2(1), makeFunc2(2)];
b[0]; // 0
b[1]; // 1
b[2]; // 2
function f1() {
  var n = 999;
  nAdd = function() {
    n += 1;
  };
  function f2() {
    console.log(n);
  }
  return f2;
}
var result = f1();
result(); // 999
nAdd();
result(); // 1000

/*-----------------------*/

function f2() {
  var n = 999;
  mAdd = function() {
    n += 1;
  };
  function f2() {
    console.log(n);
  }
  f2();
}
f2(); // 999
mAdd();
f2(); // 999
function foo1() {
  var a = 10;
  return function() {
    a *= 2;
    console.log(a);
  };
}
var f = foo1();
f(); //return 20.
f(); //return 40.

/*-------------------------*/

function foo2() {
  var a = 10;
  function f1() {
    a *= 2;
    console.log(a);
  }
  f1();
}

foo2(); //return 20.
foo2(); //return 20.
文章目录
  1. 回调
    1. 使用 this 对象的方法作为回调函数时的问题
    2. 修复上面出现的问题
    3. 回调函数特点
    4. 注意在回调函数调用时 this 的执行上下文并不是回调函数定义时的那个上下文,而是调用它的函数所在的上下文
  2. 闭包
    1. 闭包作用,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中