JS 데코레이터 함수 사용에 대한 자세한 설명
이번에는 JS 데코레이터 함수 사용에 대한 자세한 설명을 가져왔습니다. JS 데코레이터 함수 사용 시 주의사항은 무엇인가요? 실제 사례를 살펴보겠습니다.
ES6에서는 클래스 객체(예: 클래스 및 확장)의 관련 정의 및 작업이 추가되어 여러 다른 클래스 간에 일부 메서드나 동작을 공유하거나 확장할 때 그다지 우아하지 않게 됩니다. 현재 이러한 작업을 수행하는 데 도움이 되는 보다 우아한 방법이 필요합니다.
데코레이터란 무엇인가요
Python의 데코레이터
객체 지향(OOP)의 디자인 패턴에서는 데코레이터를 데코레이션 패턴이라고 합니다. OOP의 장식 모드는 상속과 조합을 통해 구현되어야 하며 Python은 OOP의 장식자를 지원하는 것 외에도 구문 수준에서 직접 장식자를 지원합니다.
파이썬에 익숙하신 분들이라면 익숙하실 겁니다. 그럼 먼저 Python의 데코레이터가 어떤 모습인지 살펴보겠습니다.
def decorator(f): print "my decorator" return f @decorator def myfunc(): print "my function" myfunc() # my decorator # my function
여기서 @designator는 우리가 데코레이터라고 부르는 것입니다. 위 코드에서는 대상 메서드를 실행하기 전에 데코레이터를 사용하여 텍스트 한 줄을 인쇄하고 원래 메서드를 수정하지 않습니다. 코드는 기본적으로 다음과 같습니다.
def decorator(f): def wrapper(): print "my decorator" return f() return wrapper def myfunc(): print "my function" myfunc = decorator(myfuc)
장식자가 우리가 장식한 대상 메서드인 매개 변수를 수신하는 것을 코드에서 보는 것은 어렵지 않습니다. 확장된 콘텐츠를 처리한 후 나중에 호출하기 위한 메서드를 반환합니다. 또한 원래 메서드 개체에 대한 액세스 권한도 잃게 됩니다. 함수에 장식을 적용할 때 실제로 장식된 메서드의 항목 참조를 변경하여 데코레이터가 반환한 메서드의 진입점을 다시 가리키도록 함으로써 원래 함수를 확장하고 수정할 수 있습니다.
ES7 데코레이터
ES7의 데코레이터도 이 구문을 사용하지만 ES5 Object.defineProperty 메서드를 사용합니다.
Object.defineProperty
Object.defineProperty() 메서드는 객체에 대한 새 속성을 직접 정의하거나 객체의 기존 속성을 수정하고 객체를 반환합니다.
이 방법을 사용하면 개체의 속성을 정확하게 추가하거나 수정할 수 있습니다. 할당에 의해 추가된 일반 속성은 속성 열거(for...in 또는 Object.keys 메서드) 중에 노출되는 속성을 생성하며 이러한 값은 변경되거나 삭제될 수 있습니다. 이 접근 방식을 사용하면 이러한 추가 세부 정보를 기본값에서 변경할 수 있습니다. 기본적으로 Object.defineProperty()를 사용하여 추가된 속성 값은 변경할 수 없습니다.
Syntax
Object.defineProperty(obj, prop, descriptor)
obj: 속성을 정의할 개체입니다.
prop: 정의하거나 수정할 속성의 이름입니다.
descriptor: 정의되거나 수정될 속성 설명자입니다.
반환 값: 함수에 전달된 개체입니다.
ES6에서는 Symbol 타입의 특수성으로 인해 Symbol 타입의 값을 객체의 키로 사용하는 것이 기존의 정의나 수정과는 다르며, Object.defineProperty는 키가 Symbol인 속성입니다.
속성 설명자
현재 객체에 존재하는 속성 설명자에는 데이터 설명자와 액세스 설명자의 두 가지 주요 형태가 있습니다.
데이터 설명자는 쓰기 가능하거나 쓰기 불가능할 수 있는 값을 가진 속성입니다.
액세스 설명자는 getter-setter 함수 쌍으로 설명되는 속성입니다.
설명자는 동시에 두 가지 형식 중 하나여야 합니다.
데이터 설명자와 액세스 설명자 모두 다음과 같은 선택적 키 값을 갖습니다.
configurable
속성의 구성 가능 항목이 true인 경우에만 속성 설명자를 변경할 수 있으며 속성 설명자를 변경할 수 있습니다. 해당 개체에서도 속성을 삭제할 수 있습니다. 기본값은 거짓입니다.
enumerable
enumerable은 for...in 루프와 Object.keys()에서 객체의 속성을 열거할 수 있는지 여부를 정의합니다.
속성의 열거 가능 속성이 true인 경우에만 속성이 객체의 열거 속성에 나타날 수 있습니다. 기본값은 거짓입니다.
데이터 설명자에는 다음과 같은 선택적 키 값도 있습니다:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的 writable 为 true 时,value 才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
用法
类的装饰
@testable class MyTestableClass { // ... } function testable(target) { target.isTestable = true; } MyTestableClass.isTestable // true
上面代码中,@testable 就是一个装饰器。它修改了 MyTestableClass这 个类的行为,为它加上了静态属性isTestable。testable 函数的参数 target 是 MyTestableClass 类本身。
基本上,装饰器的行为就是下面这样。
@decorator class A {} // 等同于 class A {} A = decorator(A) || A;
也就是说,装饰器是一个对类进行处理的函数。装饰器函数的第一个参数,就是所要装饰的目标类。
如果觉得一个参数不够用,可以在装饰器外面再封装一层函数。
function testable(isTestable) { return function(target) { target.isTestable = isTestable; } } @testable(true) class MyTestableClass {} MyTestableClass.isTestable // true @testable(false) class MyClass {} MyClass.isTestable // false
上面代码中,装饰器 testable 可以接受参数,这就等于可以修改装饰器的行为。
注意,装饰器对类的行为的改变,是代码编译时发生的,而不是在运行时。这意味着,装饰器能在编译阶段运行代码。也就是说,装饰器本质就是编译时执行的函数。
前面的例子是为类添加一个静态属性,如果想添加实例属性,可以通过目标类的 prototype 对象操作。
下面是另外一个例子。
// mixins.js export function mixins(...list) { return function (target) { Object.assign(target.prototype, ...list) } } // main.js import { mixins } from './mixins' const Foo = { foo() { console.log('foo') } }; @mixins(Foo) class MyClass {} let obj = new MyClass(); obj.foo() // 'foo'
上面代码通过装饰器 mixins,把Foo对象的方法添加到了 MyClass 的实例上面。
方法的装饰
装饰器不仅可以装饰类,还可以装饰类的属性。
class Person { @readonly name() { return `${this.first} ${this.last}` } }
上面代码中,装饰器 readonly 用来装饰“类”的name方法。
装饰器函数 readonly 一共可以接受三个参数。
function readonly(target, name, descriptor){ // descriptor对象原来的值如下 // { // value: specifiedFunction, // enumerable: false, // configurable: true, // writable: true // }; descriptor.writable = false; return descriptor; } readonly(Person.prototype, 'name', descriptor); // 类似于 Object.defineProperty(Person.prototype, 'name', descriptor);
装饰器第一个参数是 类的原型对象,上例是 Person.prototype,装饰器的本意是要“装饰”类的实例,但是这个时候实例还没生成,所以只能去装饰原型(这不同于类的装饰,那种情况时target参数指的是类本身);
第二个参数是 所要装饰的属性名
第三个参数是 该属性的描述对象
另外,上面代码说明,装饰器(readonly)会修改属性的 描述对象(descriptor),然后被修改的描述对象再用来定义属性。
函数方法的装饰
装饰器只能用于类和类的方法,不能用于函数,因为存在函数提升。
另一方面,如果一定要装饰函数,可以采用高阶函数的形式直接执行。
function doSomething(name) { console.log('Hello, ' + name); } function loggingDecorator(wrapped) { return function() { console.log('Starting'); const result = wrapped.apply(this, arguments); console.log('Finished'); return result; } } const wrapped = loggingDecorator(doSomething);
core-decorators.js
core-decorators.js是一个第三方模块,提供了几个常见的装饰器,通过它可以更好地理解装饰器。
@autobind
autobind 装饰器使得方法中的this对象,绑定原始对象。
@readonly
readonly 装饰器使得属性或方法不可写。
@override
override 装饰器检查子类的方法,是否正确覆盖了父类的同名方法,如果不正确会报错。
import { override } from 'core-decorators'; class Parent { speak(first, second) {} } class Child extends Parent { @override speak() {} // SyntaxError: Child#speak() does not properly override Parent#speak(first, second) } // or class Child extends Parent { @override speaks() {} // SyntaxError: No descriptor matching Child#speaks() was found on the prototype chain. // // Did you mean "speak"? }
@deprecate (别名@deprecated)
deprecate 或 deprecated 装饰器在控制台显示一条警告,表示该方法将废除。
import { deprecate } from 'core-decorators'; class Person { @deprecate facepalm() {} @deprecate('We stopped facepalming') facepalmHard() {} @deprecate('We stopped facepalming', { url: 'http://knowyourmeme.com/memes/facepalm' }) facepalmHarder() {} } let person = new Person(); person.facepalm(); // DEPRECATION Person#facepalm: This function will be removed in future versions. person.facepalmHard(); // DEPRECATION Person#facepalmHard: We stopped facepalming person.facepalmHarder(); // DEPRECATION Person#facepalmHarder: We stopped facepalming // // See http://knowyourmeme.com/memes/facepalm for more details. //
@suppressWarnings
suppressWarnings 装饰器抑制 deprecated 装饰器导致的 console.warn() 调用。但是,异步代码发出的调用除外。
使用场景
装饰器有注释的作用
@testable class Person { @readonly @nonenumerable name() { return `${this.first} ${this.last}` } }
有了装饰器,就可以改写上面的代码。装饰
@connect(mapStateToProps, mapDispatchToProps) export default class MyReactComponent extends React.Component {}
相对来说,后一种写法看上去更容易理解。
新功能提醒或权限
菜单点击时,进行事件拦截,若该菜单有新功能更新,则弹窗显示。
/** * @description 在点击时,如果有新功能提醒,则弹窗显示 * @param code 新功能的code * @returns {function(*, *, *)} */ const checkRecommandFunc = (code) => (target, property, descriptor) => { let desF = descriptor.value; descriptor.value = function (...args) { let recommandFuncModalData = SYSTEM.recommandFuncCodeMap[code]; if (recommandFuncModalData && recommandFuncModalData.id) { setTimeout(() => { this.props.dispatch({type: 'global/setRecommandFuncModalData', recommandFuncModalData}); }, 1000); } desF.apply(this, args); }; return descriptor; };
loading
在 React 项目中,我们可能需要在向后台请求数据时,页面出现 loading 动画。这个时候,你就可以使用装饰器,优雅地实现功能。
@autobind @loadingWrap(true) async handleSelect(params) { await this.props.dispatch({ type: 'product_list/setQuerypParams', querypParams: params }); }
loadingWrap 函数如下:、
export function loadingWrap(needHide) { const defaultLoading = ( <p className="toast-loading"> <Loading className="loading-icon"/> <p>加载中...</p> </p> ); return function (target, property, descriptor) { const raw = descriptor.value; descriptor.value = function (...args) { Toast.info(text || defaultLoading, 0, null, true); const res = raw.apply(this, args); if (needHide) { if (get('finally')(res)) { res.finally(() => { Toast.hide(); }); } else { Toast.hide(); } } }; return descriptor; }; }
问题:这里大家可以想想看,如果我们不希望每次请求数据时都出现 loading,而是要求只要后台请求时间大于 300ms 时,才显示loading,这里需要怎么改?
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
위 내용은 JS 데코레이터 함수 사용에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











CrystalDiskMark는 순차 및 무작위 읽기/쓰기 속도를 빠르게 측정하는 하드 드라이브용 소형 HDD 벤치마크 도구입니다. 다음으로 편집자님에게 CrystalDiskMark 소개와 crystaldiskmark 사용법을 소개하겠습니다~ 1. CrystalDiskMark 소개 CrystalDiskMark는 기계식 하드 드라이브와 솔리드 스테이트 드라이브(SSD)의 읽기 및 쓰기 속도와 성능을 평가하는 데 널리 사용되는 디스크 성능 테스트 도구입니다. ). 무작위 I/O 성능. 무료 Windows 응용 프로그램이며 사용자 친화적인 인터페이스와 다양한 테스트 모드를 제공하여 하드 드라이브 성능의 다양한 측면을 평가하고 하드웨어 검토에 널리 사용됩니다.

foobar2000은 언제든지 음악 리소스를 들을 수 있는 소프트웨어입니다. 모든 종류의 음악을 무손실 음질로 제공합니다. 음악 플레이어의 향상된 버전을 사용하면 더욱 포괄적이고 편안한 음악 경험을 얻을 수 있습니다. 컴퓨터에서 고급 오디오를 재생합니다. 이 장치는 보다 편리하고 효율적인 음악 재생 경험을 제공합니다. 인터페이스 디자인은 단순하고 명확하며 사용하기 쉽습니다. 또한 다양한 스킨과 테마를 지원하고, 자신의 선호도에 따라 설정을 개인화하며, 다양한 오디오 형식의 재생을 지원하는 전용 음악 플레이어를 생성합니다. 또한 볼륨을 조정하는 오디오 게인 기능도 지원합니다. 과도한 볼륨으로 인한 청력 손상을 방지하려면 자신의 청력 상태에 따라 조정하십시오. 다음엔 내가 도와줄게

NetEase Mailbox는 중국 네티즌들이 널리 사용하는 이메일 주소로, 안정적이고 효율적인 서비스로 항상 사용자들의 신뢰를 얻어 왔습니다. NetEase Mailbox Master는 휴대폰 사용자를 위해 특별히 제작된 이메일 소프트웨어로 이메일 보내기 및 받기 프로세스를 크게 단순화하고 이메일 처리를 더욱 편리하게 만듭니다. 따라서 NetEase Mailbox Master를 사용하는 방법과 그 기능이 무엇인지 아래에서 이 사이트의 편집자가 자세한 소개를 제공하여 도움을 드릴 것입니다! 먼저, 모바일 앱스토어에서 NetEase Mailbox Master 앱을 검색하여 다운로드하실 수 있습니다. App Store 또는 Baidu Mobile Assistant에서 "NetEase Mailbox Master"를 검색한 후 안내에 따라 설치하세요. 다운로드 및 설치가 완료되면 NetEase 이메일 계정을 열고 로그인합니다. 로그인 인터페이스는 아래와 같습니다.

오늘날 클라우드 스토리지는 우리의 일상 생활과 업무에 없어서는 안 될 부분이 되었습니다. 중국 최고의 클라우드 스토리지 서비스 중 하나인 Baidu Netdisk는 강력한 스토리지 기능, 효율적인 전송 속도 및 편리한 운영 경험으로 많은 사용자의 호감을 얻었습니다. 중요한 파일을 백업하고, 정보를 공유하고, 온라인으로 비디오를 시청하고, 음악을 듣고 싶은 경우 Baidu Cloud Disk는 귀하의 요구를 충족할 수 있습니다. 그러나 많은 사용자가 Baidu Netdisk 앱의 구체적인 사용 방법을 이해하지 못할 수 있으므로 이 튜토리얼에서는 Baidu Netdisk 앱 사용 방법을 자세히 소개합니다. Baidu 클라우드 네트워크 디스크 사용 방법: 1. 설치 먼저 Baidu Cloud 소프트웨어를 다운로드하고 설치할 때 사용자 정의 설치 옵션을 선택하십시오.

MetaMask(중국어로 Little Fox Wallet이라고도 함)는 무료이며 호평을 받는 암호화 지갑 소프트웨어입니다. 현재 BTCC는 MetaMask 지갑에 대한 바인딩을 지원합니다. 바인딩 후 MetaMask 지갑을 사용하여 빠르게 로그인하고 가치를 저장하고 코인을 구매할 수 있으며 첫 바인딩에는 20 USDT 평가판 보너스도 받을 수 있습니다. BTCCMetaMask 지갑 튜토리얼에서는 MetaMask 등록 및 사용 방법, BTCC에서 Little Fox 지갑을 바인딩하고 사용하는 방법을 자세히 소개합니다. MetaMask 지갑이란 무엇입니까? 3천만 명 이상의 사용자를 보유한 MetaMask Little Fox Wallet은 오늘날 가장 인기 있는 암호화폐 지갑 중 하나입니다. 무료로 사용할 수 있으며 확장으로 네트워크에 설치할 수 있습니다.

Windows 운영 체제는 세계에서 가장 인기 있는 운영 체제 중 하나이며, 새로운 버전의 Win11이 많은 주목을 받았습니다. Win11 시스템에서 관리자 권한을 얻는 것은 사용자가 시스템에서 더 많은 작업과 설정을 수행할 수 있도록 하는 중요한 작업입니다. 이번 글에서는 Win11 시스템에서 관리자 권한을 얻는 방법과 권한을 효과적으로 관리하는 방법을 자세히 소개하겠습니다. Win11 시스템에서 관리자 권한은 로컬 관리자와 도메인 관리자의 두 가지 유형으로 나뉩니다. 로컬 관리자는 로컬 컴퓨터에 대한 모든 관리 권한을 갖습니다.

OracleSQL의 나눗셈 연산에 대한 자세한 설명 OracleSQL에서 나눗셈 연산은 두 숫자를 나눈 결과를 계산하는 데 사용되는 일반적이고 중요한 수학 연산입니다. 나누기는 데이터베이스 쿼리에 자주 사용되므로 OracleSQL에서 나누기 작업과 사용법을 이해하는 것은 데이터베이스 개발자에게 필수적인 기술 중 하나입니다. 이 기사에서는 OracleSQL의 나누기 작업 관련 지식을 자세히 설명하고 독자가 참고할 수 있는 특정 코드 예제를 제공합니다. 1. OracleSQL의 Division 연산

Apple은 화요일에 iOS 17.4 업데이트를 출시하여 iPhone에 수많은 새로운 기능과 수정 사항을 추가했습니다. 업데이트에는 새로운 이모티콘이 포함되어 있으며 EU 사용자는 다른 앱 스토어에서도 해당 이모티콘을 다운로드할 수 있습니다. 또한, 업데이트는 iPhone 보안 제어를 강화하고 사용자에게 더 많은 선택권과 보호 기능을 제공하기 위해 더 많은 "도난당한 장치 보호" 설정 옵션을 도입합니다. "iOS17.3에서는 최초로 '도난 기기 보호' 기능을 도입해 사용자의 민감한 정보에 대한 보안을 강화했습니다. 사용자가 집이나 기타 친숙한 장소를 떠나 있을 때 이 기능을 사용하려면 먼저 생체 정보를 입력해야 합니다. Apple ID 암호 변경, 도난 기기 보호 끄기 등 특정 데이터에 접근하고 변경하려면 정보를 다시 입력해야 합니다.
