普通函数基本用法
function fn(name,age=17){
console.log(name+","+age);
}
fn("Amy",18); // Amy,18
fn("Amy",""); // Amy,
fn("Amy"); // Amy,17
只有在未传递参数,或者参数为 undefined 时,才会使用默认参数,null 值被认为是有效的值传递。
function fn(name,age=17){
console.log(name+","+age);
}
fn("Amy",null); // Amy,null
不定参数:不定参数用来表示不确定参数个数,形如,...变量名,由 ... 加上一个具名参数标识符组成。具名参数只能放在参数组的最后,并且有且只有一个不定参数。
function f(...values){
console.log(values.length);
}
f(1,2); // 2
f(1,2,3,4); // 4
this 和箭头函数
箭头函数提供了一种更加简洁的函数书写方式。基本语法是:
参数 => 函数体
var f = v => v;
// 等价于
var f = function(v){
return v;
}
f(1); // 1
-
当箭头函数没有参数或者有多个参数,要用 () 括起来。
var f = (a,b) => { let result = a+b; return result; } f(6,2); // 8 -
当箭头函数要返回对象的时候,为了区分于代码块,要用 () 将对象包裹起来。
// 报错 var f = (id,name) => {id: id, name: name}; f(6,2); // SyntaxError: Unexpected token : // 不报错 var f = (id,name) => ({id: id, name: name}); f(6,2); // {id: 6, name: 2}
学习如何在 JavaScript 里正确使用 this 就好比一场成年礼。
JavaScript 里,this 的值在普通函数被调用的时候才会指定(箭头函数恰恰相反)。这是个既强大又灵活的特点,但是你需要花点时间弄清楚函数调用的上下文是什么。但众所周知,这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候。
-
箭头函数能保存函数创建时的
this值,而不是调用时的值。function fn(){ setTimeout(()=>{ // 定义时,this 绑定的是 fn 中的 this 对象 console.log(this.a); },0) } var a = 20; // fn 的 this 对象为传入的参数: {a: 19} fn.call({a: 18}); // 18- 箭头函数根本没有自己的
this,导致箭头函数体内部的this就是外层函数体的this,即从作用域链的上一层继承this。 - 若普通函数是一个对象的方法,则它的
this指针指向这个对象 - ES6 之前,JavaScript 的
this对象一直很令人头大,回调函数,经常看到var self = this这样的代码,为了将外部this传递到回调函数中,那么有了箭头函数,就不需要这样做了,直接使用this就行。
/**普通回调函数 */ function fn1() { // var self = this setTimeout(function() { console.log("id:", this.id) }, 0) } fn1.call({id: 12}) // 如果注释掉 `var self = this`, 则:id: undefined /**箭头回调函数 */ function foo() { setTimeout(() => { console.log('id:', this.id); }, 0); } foo.call({ id: 42 }); // id: 42 /**对象里的箭头函数 */ var age = 20; var Person1 = { 'age': 18, 'sayHello': function () { setTimeout(()=>{ console.log(this.age); }); } }; Person1.sayHello(); // 18 - 箭头函数根本没有自己的
-
下面看一个例子
let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function() { return function() { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return {suit: this.suits[pickedSuit], card: pickedCard % 13}; } } } let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit);可以看到
createCardPicker是个函数,并且它又返回了一个函数。 如果我们尝试运行这个程序,会发现它并没有弹出对话框而是报错了。 因为createCardPicker返回的函数里的this被设置成了window而不是deck对象。 因为我们只是独立的调用了cardPicker()。 顶级的非方法式调用会将this视为window。 (注意:在严格模式下,this为undefined而不是window)。为了解决这个问题,我们可以在函数被返回时就绑好正确的
this。 这样的话,无论之后怎么使用它,都会引用绑定的deck对象。 我们需要改变函数表达式来使用 ECMAScript 6 箭头语法。 箭头函数能保存函数创建时的this值,而不是调用时的值:let deck = { suits: ["hearts", "spades", "clubs", "diamonds"], cards: Array(52), createCardPicker: function() { // NOTE: 箭头函数能保存函数创建时的 `this` 值 return () => { let pickedCard = Math.floor(Math.random() * 52); let pickedSuit = Math.floor(pickedCard / 13); return {suit: this.suits[pickedSuit], card: pickedCard % 13}; } } } let cardPicker = deck.createCardPicker(); let pickedCard = cardPicker(); console.log("card: " + pickedCard.card + " of " + pickedCard.suit);还有:
class Handler { info: string; onClickGood = (e: Event) => { this.info = e.message } } let h = new Handler(); uiElement.addClickListener(h.onClickGood);
箭头函数不适用的场景
-
在对象里定义的函数,且该函数内部包括
this的时候,不适用。若对象里面的函数使用箭头函数。
const cat = { lives: 9, jumps: () => { this.lives--; } }; cat.jumps(); console.log(cat.lives); // 9 //若改成这样,在对象的方法中返回箭头函数,并且立即执行,则可以达成效果,这是因为箭头函数的 `this`是 jumps 函数方法的 `this`,而该 this 指向本对象 const catt = { lives: 9, jumps() { return () => {this.lives--} } } let jump = catt.jumps() jump() // 立即执行 console.log("catt:", catt.lives) // 8若对象里面的函数使用普通函数。
const cat = { lives: 9, jumps() { this.lives--; } }; cat.jumps(); console.log(cat.lives); // 8第一个代码中,
cat.jumps()方法是一个箭头函数,这是错误的。调用cat.jumps()时,如果是普通函数,该this指向cat对象;如果写成上面那样的箭头函数,不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时指的是 window。 -
回调函数(callback)里的
this参数当你将一个函数传递到另一个函数里调用时,你可能见到过回调函数里的
this会报错。 因为当回调函数被调用时,它会被当成一个普通函数调用,this将为undefined或者window。var clientData = { id: 096545, fullName: "Not Set", // setUsrName 是一个在 clientData 对象中的方法 setUserName: function (firstName, lastName){ this.fullName = firstName + " " + lastName; } } function getUserInput(firstName, lastName, callback){ // 调用回调函数 callback(firstName, lastName); } getUserInput("Barack","Obama",clientData.setUserName); console.log(clientData.fullName); // Not Set console.log(window.fullName); // Barack Obama使用
Call和Apply函数来改变this指向:每个 Javascript 中的函数都有两个方法:
call和apply。这些方法被用来设置函数内部的this对象以及给此函数传递变量。这里我们演示
apply函数实现,call函数类似。(call接收的第一个参数默认被用来在函数内部当做this的对象(类似 python 类方法的self),传递给函数的其他参数被挨个传递。)注:
apply函数的第一个参数也是在函数内部作为this的对象,然而后面的参数却是传递给函数的参数组成的数组。//注意到我们增加了新的参数作为回调对象,叫做“callbackObj” function getUserInput(firstName, lastName, callback ,callbackObj){ //code ..... callback.apply(callbackObj, [firstName, lastName]); //callback.call(callbackObj, firstName, lastName); } getUserInput("Barack", "Obama", clientData.setUserName, clientData); console.log(clientData.fullName); //Barack Obama -
需要动态this时,也不应该使用动态函数。
var btn = document.getElementById('btn'); btn.addEventListener('click', () => { console.log(this); });因为
btn的监听函数是一个箭头函数,导致里面的this就是全局对象,而不符合我们想操作按钮本身的需求。如果改成普通函数,this就会动态指向被点击的按钮对象。
参考:
本文深入探讨了JavaScript中箭头函数的特性与用法,包括其如何改变this的指向,以及在不同场景下的应用技巧。
1440

被折叠的 条评论
为什么被折叠?



