日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

箭头函数的this指向谁_高阶函数

發(fā)布時間:2024/7/23 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 箭头函数的this指向谁_高阶函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

NodeJS 系列文章,本篇是第一篇,首先,預(yù)計將后續(xù)高頻使用邏輯串一遍,依次是高階函數(shù),promise以及事件機(jī)制。本篇主要是高階函數(shù)。

call、bind、apply

  • call、apply 都是改變 this 指向,區(qū)別是接受參數(shù)的方式不一樣,call 一個一個傳參數(shù),apply 接收一個數(shù)組。
  • bind 會創(chuàng)建一個新函數(shù),稱為綁定函數(shù),當(dāng)調(diào)用這個綁定函數(shù)時,綁定函數(shù)會以創(chuàng)建它時傳入 bind 方第一個參數(shù)作為 this,傳入 bind 的第二個以及以后的參數(shù)加上綁定函數(shù)運(yùn)行時本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。
  • 當(dāng)你希望改變上下文環(huán)境之后并非立即執(zhí)行,而是回調(diào)執(zhí)行的時候,使用 bind() 方法,bind 是返回的函數(shù)。
  • apply、call 則會立即執(zhí)行函數(shù)。

this 指向

this 指向問題,誰調(diào)用,我就指向誰。

全局上下文

非嚴(yán)格模式和嚴(yán)格模式中this都是指向頂層對象(瀏覽器中是window)。

console.log(this === window); // true'use strict'console.log(this === window); // truethis.name = 'Hiraku';console.log(this.name); // Hiraku

函數(shù)上下文

普通函數(shù)調(diào)用模式

var name = '驍媽';var func = function() {console.log(this === window, this.name); // true 驍媽(瀏覽器)}; func();

在 ES5 中,全局變量是掛載在頂層對象(瀏覽器是 window )中。

const name1 = 'mahongqin';const func1 = function() {console.log(this === window, this.name1); // true undefined};const func2 = () => {console.log(this === window, this.name1); // true undefined};func1();func2();

let 沒有給頂層對象中(瀏覽器是 window )添加屬性,window.name1 和 window.func1,window.func2 都是 undefined。

嚴(yán)格模式中,普通函數(shù)中的 this 則表現(xiàn)不同,表現(xiàn)為 undefined。

'use strict';var name2 = '驍媽';var func3 = function() {console.log(this === window); // false}; func3();

call,apply 作用之一就是改變函數(shù)的 this 指向為第一個參數(shù)。 如果第一個參數(shù)是 undefined 或者 null,非嚴(yán)格模式下,是指向 window。嚴(yán)格模式下,就是指向第一個參數(shù)。

對象中的函數(shù)(方法)調(diào)用模式

var name3 = 'Hiraku_Ma';var func4 = function() {console.log(this, this.name);}var obj = {name: 'mhq',func: func4,attr: {name: 'mhq-gs',func: func4,}}obj.func(); // Object{} obj 'mhq'obj.attr.func(); // Object{} obj.attr 'mhq-gs'// 用call類比則為:obj.func.call(obj); // 'mhq'// 用call類比則為:obj.attr.func.call(obj.attr); // 'mhq-gs'

函數(shù)賦值之后變成普通函數(shù)。

構(gòu)造函數(shù)調(diào)用模式

function Example(type){this.type = type;console.log(this);// return this; } var exp = new Example('mhq');

使用 new 操作符調(diào)用函數(shù),會自動執(zhí)行以下步驟:

  • 創(chuàng)建了一個全新的對象。
  • 這個對象會被執(zhí)行[[Prototype]](也就是proto)鏈接。
  • 生成的新對象會綁定到函數(shù)調(diào)用的 this。
  • 通過 new 創(chuàng)建的每個對象將最終被[[Prototype]]鏈接到這個函數(shù)的 prototype 對象上。
  • 如果函數(shù)沒有返回對象類型 Object( 包含 Functoin, Array, Date, RegExg, Error ),那么 new 表達(dá)式中的函數(shù)調(diào)用會自動返回這個新的對象。

new 操作符調(diào)用時,this 指向生成的新對象。 new 調(diào)用時的返回值,如果沒有顯式返回對象或者函數(shù),才是返回生成的新對象。

function Example(type){this.type = type;console.log(this);return {};}var exp = new Example('mhq'); // { name: mhq }console.log(exp);// 如果返回函數(shù) f ,則 exp 是函數(shù) f,如果是對象 {} ,則 exp 是對象 {}

原型鏈中的調(diào)用模式

function Example(type){this.type = type;console.log(this);}Example.prototype.func = function() {console.log(this.type);};var exp = new Example('mhq');exp.func();

箭頭函數(shù)調(diào)用模式

var name = 'mhq';var student = {name: 'hiraku',func: function () {var arrowFunc = () => {console.log(this.name);}arrowFunc();},arrowFunc2: () => {console.log(this.name);}}student.func(); // 'hiraku'student.arrowFunc2(); // 'mhq'
  • 語法更加簡潔、清晰
  • 箭頭函數(shù)不會創(chuàng)建自己的 this
  • 箭頭函數(shù)的 this 指向定義時所在的外層第一個普通函數(shù),跟使用位置沒有關(guān)系
  • 被繼承的普通函數(shù)的 this 指向改變,箭頭函數(shù)的 this 指向會跟著改變
  • 箭頭函數(shù)外層沒有普通函數(shù),嚴(yán)格模式和非嚴(yán)格模式下它的 this 都會指向 window (全局對象)
  • call()、apply()、bind() 無法改變箭頭函數(shù)中 this 的指向
  • 箭頭函數(shù)不能作為構(gòu)造函數(shù)使用
  • 箭頭函數(shù)沒有自己的 arguments
  • 箭頭函數(shù)的 this 指向全局,使用 arguments 會報未聲明的錯誤
  • 箭頭函數(shù)的 this 指向普通函數(shù)時,它的 arguments 繼承于該普通函數(shù)
  • rest參數(shù)(...擴(kuò)展符)取參數(shù)
  • 箭頭函數(shù)沒有原型 prototype
  • 箭頭函數(shù)不能用作 Generator 函數(shù),不能使用 yeild 關(guān)鍵字
var obj = {name: 'mhq',func: function () {console.log(this.name);return () => {console.log('arrowFn:', this.name);}}}var obj1 = {name: 'hiraku',}obj.func().call(obj1); // 'mhq' 'arrowFn:' 'mhq'obj.func.call(obj1)(); // 'hiraku' 'arrowFn:' 'hiraku'

DOM 事件處理函數(shù)調(diào)用

  • onclick 和 addEventerListener 是指向綁定事件的元素。
  • 一些瀏覽器,比如 IE6~IE8 下使用 attachEvent,this 指向是 window。

高階函數(shù)(Higher-order function)

什么是高階函數(shù)?高階函數(shù)至少滿足兩個條件:接受一個或多個函數(shù)作為輸入,輸出一個函數(shù)。也可以這樣理解,一個函數(shù)的參數(shù)是一個函數(shù)(回調(diào)函數(shù));一個函數(shù)返回一個函數(shù)(函數(shù)柯里化)。

我們寫代碼時不希望破壞原有邏輯,所以將原有邏輯包上一個函數(shù),這個函數(shù)內(nèi)部實(shí)現(xiàn)自己的邏輯,即切片編程。

const originFunc = (...args) => {console.log('原函數(shù)', args);};// 希望在調(diào)用 originFunc 之前做一些事情,使用 Function.prototype 給每個函數(shù)擴(kuò)展一些功能Function.prototype.before = function(cb) {return (...args) => {cb();this(...args);};};let newFunc = originFunc.before(() => {console.log('before originFunc');});newFunc('a', 'b', 'c');

一個異步并發(fā)問題

我同時發(fā)送多個請求,希望拿到最終的結(jié)果

function after(time, fn) {return () => {if (--time === 0) {fn();}};}const exaFun = after(3, () => {console.log('執(zhí)行');});exaFun();exaFun();exaFun();

示例:

const fs = require('fs');const path = require('path');function run(times, fn) {const renderObj = {};return (key, value) => {renderObj[key] = value;console.log(key, value);if(--times === 0) fn(renderObj);};}let out = run(2, (result) => {console.log(result);});fs.readFile(path.resolve(__dirname, '1.txt'), 'utf8', (_, data) => {console.log(data, 'ddd')out('1', data);});fs.readFile(path.resolve(__dirname, '2.txt'), 'utf8', (_, data) => {out('2', data);});

函數(shù)柯里化

柯里化,即 Currying,為了給多參數(shù)函數(shù)提供了一個遞歸降解的方式,把提供多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)的函數(shù),并且返回余下參數(shù)而且返回結(jié)果的新函數(shù)。

const curring = (fn, arr = []) => {// 長度值的是參數(shù)個數(shù)let len = fn.length;return (...arg) => {arr = [...arr, ...arg];if (arr.length < len) return curring(fn, arr);return fn(...arr);};};const add = (a, b, c, d, e, f, g, h) => {return a + b + c + d + e + f + g + h;}console.log(curring1(add, [1, 2])(3, 4)(5)(6)(7, 8)) // 15

函數(shù)柯里化使用場景: 參數(shù)復(fù)用 延遲執(zhí)行 預(yù)加載 動態(tài)創(chuàng)建函數(shù)

發(fā)布訂閱、觀察者模式

觀察者模式 定義了對象間的一種一對多的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都將得到通知,并自動更新 屬于行為型模式,行為型模式關(guān)注的是對象之間的通訊 * 觀察者和被觀察者之間的通訊

const fs = require('fs');const e = {arr: [],on(fn) {this.arr.push(fn);},emit() {this.arr.forEach(fn => fn());}};e.on(() => {console.log('讀取到了數(shù)據(jù)');})const renderObj = {};e.on(() => {if (Object.keys(renderObj).length === 2) {console.log('都讀取完畢了');}});fs.readFile('./name.txt', 'utf8', (_, data) => {renderObj['name'] = data;e.emit();});fs.readFile('./age.txt', 'utf8', (_, data) => {renderObj['age'] = data;e.emit();});

發(fā)布訂閱 就是事先存儲好,稍后發(fā)布的時候讓事先訂閱的事執(zhí)行 發(fā)布者并不會直接通知訂閱者,換句話說,發(fā)布者和訂閱者,彼此互不相識 * 在發(fā)布者和訂閱者之間存在第三個組件,稱為調(diào)度中心或事件通道,它維持著發(fā)布者和訂閱者之間的聯(lián)系,過濾所有發(fā)布者傳入的消息并相應(yīng)地分發(fā)它們給訂閱者

class Subject { // 被觀察者constructor(name) {this.name = name;this.arr = [];this.state = '我很開心';}attach(observer) { // 注冊觀察者 基于發(fā)布訂閱this.arr.push(observer);}setState(newState) {this.state = newState;this.arr.forEach(o => o.update(this)); // 通知所有觀察者 我的狀態(tài)發(fā)生了變化}}class Observer { // 觀察者constructor(name) {this.name = name;}update(s) {console.log(s.name + '當(dāng)前狀態(tài)是' + s.state + '對:' + this.name);}}let s = new Subject('小寶寶');let o1 = new Observer('我');let o2 = new Observer('我媳婦');s.attach(o1);s.attach(o2);console.log(s.state);s.setState('不開心了');

本篇文章涉及到的高階函數(shù)使用有函數(shù)柯里化、發(fā)布訂閱|觀察者模式等。下篇將分享 Promise 源碼,手寫 Promise。

總結(jié)

以上是生活随笔為你收集整理的箭头函数的this指向谁_高阶函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。