1# Class property and descriptor 2 3Property descriptor for use with `Napi::ObjectWrap<T>` and 4`Napi::InstanceWrap<T>`. This is different from the standalone 5`Napi::PropertyDescriptor` because it is specific to each 6`Napi::ObjectWrap<T>` and `Napi::InstanceWrap<T>` subclasses. 7This prevents using descriptors from a different class when defining a new 8class (preventing the callbacks from having incorrect `this` pointers). 9 10`Napi::ClassPropertyDescriptor` is a helper class created with 11`Napi::ObjectWrap<T>` and `Napi::InstanceWrap<T>`. For more reference about it 12see: 13 14- [InstanceWrap](./instance_wrap.md) 15- [ObjectWrap](./object_wrap.md) 16 17## Example 18 19```cpp 20#include <napi.h> 21 22class Example : public Napi::ObjectWrap<Example> { 23 public: 24 static Napi::Object Init(Napi::Env env, Napi::Object exports); 25 Example(const Napi::CallbackInfo &info); 26 27 private: 28 double _value; 29 Napi::Value GetValue(const Napi::CallbackInfo &info); 30 void SetValue(const Napi::CallbackInfo &info, const Napi::Value &value); 31}; 32 33Napi::Object Example::Init(Napi::Env env, Napi::Object exports) { 34 Napi::Function func = DefineClass(env, "Example", { 35 // Register a class instance accessor with getter and setter functions. 36 InstanceAccessor<&Example::GetValue, &Example::SetValue>("value"), 37 // We can also register a readonly accessor by omitting the setter. 38 InstanceAccessor<&Example::GetValue>("readOnlyProp") 39 }); 40 41 Napi::FunctionReference *constructor = new Napi::FunctionReference(); 42 *constructor = Napi::Persistent(func); 43 env.SetInstanceData(constructor); 44 exports.Set("Example", func); 45 46 return exports; 47} 48 49Example::Example(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Example>(info) { 50 Napi::Env env = info.Env(); 51 // ... 52 Napi::Number value = info[0].As<Napi::Number>(); 53 this->_value = value.DoubleValue(); 54} 55 56Napi::Value Example::GetValue(const Napi::CallbackInfo &info) { 57 Napi::Env env = info.Env(); 58 return Napi::Number::New(env, this->_value); 59} 60 61void Example::SetValue(const Napi::CallbackInfo &info, const Napi::Value &value) { 62 Napi::Env env = info.Env(); 63 // ... 64 Napi::Number arg = value.As<Napi::Number>(); 65 this->_value = arg.DoubleValue(); 66} 67 68// Initialize native add-on 69Napi::Object Init (Napi::Env env, Napi::Object exports) { 70 Example::Init(env, exports); 71 return exports; 72} 73 74// Register and initialize native add-on 75NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init) 76``` 77 78The above code can be used from JavaScript as follows: 79 80```js 81'use strict'; 82 83const { Example } = require('bindings')('addon'); 84 85const example = new Example(11); 86console.log(example.value); 87// It prints 11 88example.value = 19; 89console.log(example.value); 90// It prints 19 91example.readOnlyProp = 500; 92console.log(example.readOnlyProp); 93// Unchanged. It prints 19 94``` 95 96## Methods 97 98### Constructor 99 100Creates new instance of `Napi::ClassPropertyDescriptor` descriptor object. 101 102```cpp 103Napi::ClassPropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {} 104``` 105 106- `[in] desc`: The `napi_property_descriptor` 107 108Returns new instance of `Napi::ClassPropertyDescriptor` that is used as property descriptor 109inside the `Napi::ObjectWrap<T>` class. 110 111### Operator 112 113```cpp 114operator napi_property_descriptor&() { return _desc; } 115``` 116 117Returns the original Node-API `napi_property_descriptor` wrapped inside the `Napi::ClassPropertyDescriptor` 118 119```cpp 120operator const napi_property_descriptor&() const { return _desc; } 121``` 122 123Returns the original Node-API `napi_property_descriptor` wrapped inside the `Napi::ClassPropertyDescriptor` 124