Ver Fonte

JS Object

usuiforhe há 4 anos atrás
pai
commit
2c228eb988
1 ficheiros alterados com 254 adições e 3 exclusões
  1. 254 3
      TS/JaveScript.md

+ 254 - 3
TS/JaveScript.md

@@ -3,7 +3,7 @@
  * @Autor: LC
  * @Autor: LC
  * @Date: 2022-01-20 10:45:55
  * @Date: 2022-01-20 10:45:55
  * @LastEditors: Please set LastEditors
  * @LastEditors: Please set LastEditors
- * @LastEditTime: 2022-01-23 01:47:10
+ * @LastEditTime: 2022-01-24 01:12:58
  * @Description: file content
  * @Description: file content
 -->
 -->
 # JavaScipt语法
 # JavaScipt语法
@@ -458,7 +458,7 @@ function hyCompose(...fns){
 }
 }
 ```
 ```
 
 
-## JS其他知识
+### JS其他函数知识
 
 
 ```js
 ```js
 var message = "VO : GO";
 var message = "VO : GO";
@@ -490,4 +490,255 @@ eval(jsString;)
 >> 运行中可能被篡改  
 >> 运行中可能被篡改  
 >> 不能被js引擎优化,因为是`eval`去执行的不经过引擎
 >> 不能被js引擎优化,因为是`eval`去执行的不经过引擎
 
 
-## JS的面向对象
+## JS的面向对象
+
+面向对象是现实的抽象方式  
+
+对象是JavaScript中一个非常重要的概念,因为对象可以**将多个相关联的数据封装**到一起,更好的**描述一个事物**  
+
+- JavaScript支持多种编程范式,包括**函数式编程**和**面向对象编程**
+  - JS对象被设计成一组**属性的无序集合**,像是一个**哈希表**,有**K/V组成**
+  - **key是一个标识符名称**,**value可以是任意类型**,也可以是**其他对象或函数类型**
+  - 如果值是一个函数,我们称之为对象的方法
+
+-------
+
+### 创建对象
+
+```js
+// 创建对象 方式1 使用Object类和new关键字来创建对象
+var obj2 = new Object();
+obj.name = "y";
+obj.age = 15;
+obj.height = 180;
+
+// 创建对象 方式2 通过 字面量 的方式
+var obj = {
+    name : "y",
+    age : 15,
+    height : 180,
+    eat : function() {
+        console.log("在吃饭");
+    }
+};
+```
+
+> `{}`是字面量,可以立即求值,而`new Object()`本质上是方法(只不过这个方法是内置的)调用,既然是方法调用,就涉及到在proto链中遍历该方法,当找到该方法后,又会生产方法调用必须的堆栈信息,方法调用结束后,还要释放该堆栈
+
+### 操作对象属性
+
+```js
+var obj = {
+    name : "y",
+    age : 16
+};
+
+console.log(obj.name);      // 获取属性
+obj.name = "j";             // 修改属性
+delete obj.name;            // 删除属性
+
+for (var key in obj){       // 遍历属性
+    console.log(key);
+}
+```
+
+上述对象的属性都是**直接定义在对象内部**,或者**直接添加到对象内部**的,这样做**不能对这个属性进行一些限制**:比如是否可以delete/被遍历等  
+
+为了对属性进行比较精准的操作控制,我们可以使用**属性描述符**,通过属性描述符**可以精准的添加或修改对象的属性**,属性描述符需要使用`Object.defineProperty`来对属性进行添加或修改  
+
+```js
+// obj : 对象、prop : 属性、descriptor : 属性描述符
+Object.defineProperty(obj, prop, descriptor);
+```
+
+`Object.defineProperty()`会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并**返回此对象**  
+
+> 该方法会返回被修改的对象,原本的对象也会被修改,所以可以不用接收函数返回值,并且可以发现该函数并非**纯函数**
+
+- 属性描述符
+  - 数据属性描述符
+  - 存取属性描述符
+
+|            | configurable | enumerable | value  | writable | get    | set    |
+| ---------- | ------------ | ---------- | ------ | -------- | ------ | ------ |
+| 数据描述符 | 可以         | 可以       | 可以   | 可以     | 不可以 | 不可以 |
+| 存取描述符 | 可以         | 可以       | 不可以 | 不可以   | 可以   | 可以   |
+
+- `configurable` 属性是否可以通过delete删除属性,是否可以修改其特性或者修改为存取描述符
+  - 直接在一个对象上定义某个属性时,默认为true
+  - 通过属性描述符定义也给属性时,默认为false
+
+- `enumerable` 属性是否可以通过for-in或者Object.keys()返回该属性
+  - 直接在一个对象上定义某个属性时,`enumerable`为true
+  - 通过属性描述符定义属性时,`enumerable`为false
+
+- `writable` 是否可以修改属性的值
+  - 直接在一个对象上定义某个属性时,`writable`为true
+  - 通过属性描述符定义一个属性时,`writable`为false
+- `value` 的具体值,读取属性时返回该值,修改属性时修改该值
+  - 默认情况下`value`是`undefined`的
+- get/get,为获得和设置使用的函数
+
+
+- 存取属性描述符:只能设置`configurable`,`enumerable`,`get`,`set`
+- 数据属性描述符,只能设置`configurable`,`enumerable`,`writable`,`value`
+
+> 个人理解:  
+> 对于不需要进行额外处理的数据可以使用**数据属性描述符**,比如`PI = 3.1415926`  
+> 对于需要额外处理的数据,比如年龄只能是10~20就需要使用**存取属性描述符**  
+
+```js
+var obj = {
+    name : "y",
+    age : 16
+};
+
+// obj对象不存在height属性,则先添加height属性,再设置其属性描述
+Object.defineProperty(obj, 'height', {
+    value : 180
+});  
+
+console.log(obj);
+
+```
+
+> 这里obj并不会输出height属性,因为`height`是通过属性描述符添加的所以`enumerable`默认为false
+
+```js
+// configurable展示
+// obj就是前面的obj
+Object.defineProperty(obj, 'height', {
+    value : 180,
+    configurable : false,
+});  
+delete obj.name
+console.log(obj.name);    // undefined
+
+delete obj.height
+console.log(obj.height);    // 180 没有被删除
+
+Object.defineProperty(obj, 'height', {
+    value : 200,
+    configurable : true,
+});  
+console.log(obj.height);    // 180 没有被修改成200,因为configurable最开始是false
+```
+
+```js
+// enumerable展示
+Object.defineProperty(obj, 'height', {
+    value : 180,
+    configurable : false,
+    enumerable : true
+});  
+console.log(obj);       // 此时可以正常打印出height属性
+
+```
+
+```js
+var obj = {
+    name : "y",
+    age : 16 ,
+    _address : "private"    // 个人习惯:前面有个下划线表示私有变量
+};
+
+Object.defineProperty(obj, 'address', {
+    configurable : true,
+    enumerable : true,
+    get : function () {
+        return this._address;  
+    },
+    set : function(value){
+        this._address = value;
+    }
+});  
+```
+
+> 这里使用`address`属性作为`_address`属性的代理  
+> 因为`_address`作为私有变量不希望外界随意读取,所以使用`address`代理的方法
+
+- 定义多个属性描述符
+
+```js
+var obj = {
+    _age : 0,
+}
+Object.defineProperties(obj, {
+    name : {
+        configurable : true,
+        enumerable : true,
+        writable : true,
+        value : "y"
+    },
+    age : {
+        configurable : true,
+        enumerable : true,
+        get : function (){
+            return this._age;
+        },
+        set : function (value) {
+            this._age = value;
+        }
+    }
+});
+console.log(obj);
+```
+
+- 另一种使用get/set的方法
+
+```js
+var obj = {
+    _age : 10,
+    set age(value){
+        this._age = value;
+    },
+    get age() {
+        return this._age;
+    }
+}
+obj.age = 20;
+console.log(obj);
+```
+
+- 获得对应属性的属性描述符
+
+```js
+var obj = {
+    _age: 0,
+}
+console.log(Object.getOwnPropertyDescriptor(obj, "_age"));
+```
+
+- 获得对象的所有属性描述符
+
+```js
+var obj = {
+    name: "y",
+    age: 16,
+    _address: "private"
+};
+console.log(Object.getOwnPropertyDescriptors(obj));
+```
+
+### 对对象的限制
+
+- 禁止对象继续添加新的属性
+
+```js
+Object.preventExtensions(obj);
+```
+
+- 禁止对象配置/删除属性
+
+```js
+Object.seal(obj);
+```
+
+- 让对象属性变成不可修改(writable : false)
+
+```js
+Object.freeze(obj);
+```
+
+### 创建多个对象的方案
+