List of new ES5 features

overview

ECMAScript 5.1 is what we often call es5. It was made public in 2012. Today, except for some lower versions of browsers, all major mainstream browsers have implemented support for most of the features of es5.
Digital management platform
Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus
Vue authority system case
personal blog address
First, a piece of code, experience:

<body>
<h2>单项数据绑定:通过修改JS中的数据,页面呈现最新修改的数据信息。这是一种映射关系,把JS数据的变化映射到DOM结构上</h2>
<div id="box">数据单项绑定呈现位置</div>
<input type="text" id="ipt">
</body>
<script src="./js/jquery-1.12.3.min.js"></script>
<script>
    // 创建对象
    // var obj = {
    
    
    //     des:"把Model的变化映射到DOM结构上"
    // }

    // 获取元素
    // var box = document.getElementById("box");

    // // 设置元素的内部文本
    // box.innerHTML = obj.des;

    // 普通的方式,修改对象的值,查看页面DOM数据变化
    // obj.des = "新的数据";//页面不会发生改变,除非通过innerHTML重新写入

    // 通过set方法设置单项绑定
    // Object.defineProperty(obj,'des',{
    
    
    //     //赋值器
    //     set:function(value){
    
    
    //         // 当设置或修改新的值时,将最新的值输出到页面
    //         box.innerHTML = value;
    //         // 备用属性赋值
    //         this.oDes = value;
    //     },
    //     // 取值器
    //     get:function(){
    
    
    //         return this.oDes;
    //     }
    // });

    // 再次修改以下值试试
    // obj.des = "新的值";//发现页面内容更新了


    // 现在我们做这样一个修改,页面添加一个输入框,随着输入框内容的输入,上面呈现输入框中的内容,修改如下:
    // 创建对象
    var obj = {
    
    
        des:"把Model的变化映射到DOM结构上"
    }

    // 获取元素
    var box = document.getElementById("box");
    var ipt = document.getElementById("ipt");

    // 设置元素的内部文本
    box.innerHTML = obj.des;
    Object.defineProperty(obj,'des',{
    
    
        //赋值器
        set:function(value){
    
    
            // 当设置或修改新的值时,将最新的值输出到页面
            box.innerHTML = value;
            // 备用属性赋值
            this.oDes = value;
        },
        // 取值器
        get:function(){
    
    
            return this.oDes;
        }
    });

    // 新的值来自于页面输入框 触发正在输入事件
    // ipt.oninput = function(){
    
    
    //     if(this.value === ""){
    
    
    //         box.innerHTML = "把Model的变化映射到DOM结构上";
    //     }else{
    
    
    //         obj.des = this.value;
    //     }
    // }
    
    // 含有输入法时,不能检测中文,改造并使用jQuery(使用js也可)如下:

    /**
    * 拓展:实现中文输入法下,仅在选词后触发input事件
    * 描述:在使用oninput监控输入框内容变化时,我们期望仅在value值变化时,才触发oninput事件,而在中文输入下,未选词时的按键也会触发oninput事件。
    * 两个事件:
    *   compositionstart事件
    *   compositionend事件
    * 实现方式:使用一个变量表示拼写状态,在oninput事件中判断是否在拼写状态,当拼写状态结束,继续执行下一步操作。
    * 代码示例如下:
    **/
    // 定义是否开启输入法的开关 默认关闭
    var flag = false;
    //oninput在oncompositionend之前执行,需加定时器
    ipt.oninput = function(){
    
    
        this.addEventListener('compositionstart',function(){
    
    //中文开始书写
            flag = true;//检测到中文输入法开启,设为true
        })
        this.addEventListener('compositionend',function(){
    
    //中文书写完毕,选取文字完毕
            flag = false;//输入完毕,设置false
        })
        setTimeout(function() {
    
    
            if(!flag) {
    
    //保证输入法没有开启也能正常获取数据
                if(ipt.value === ""){
    
    
                    box.innerHTML = "把Model的变化映射到DOM结构上";
                }else{
    
    
                    obj.des = ipt.value;
                }
            }
        },0);
    }
</script>

1. Strict mode

1.1 Basic overview

In addition to the normal operating mode (mixed mode), ES5 has added a second operating mode: "strict mode" (strict mode),
as the name implies, this mode makes JavaScript run under stricter syntax.
"Strict mode" embodies Javascript A more reasonable, safer, and more rigorous development direction, mainstream browsers including IE 10 have already supported it, and many large projects have begun to fully embrace it.
On the other hand, the same code may have different running results in "strict mode"; some statements that can run in "normal mode" will not run in "strict mode". Mastering these contents will help you understand Javascript in a more detailed and in-depth manner, and make you a better programmer

1.2 Purpose of setting strict mode

Eliminate some unreasonable and imprecise parts of JavaSript syntax, reduce some weird behaviors,
eliminate some unsafe parts of code operation, and protect the safe operation of code
Improve compiler efficiency and increase running speed
for future new versions of JavaScript good foreshadowing

1.3 How to use

Globally or inside a function, the first statement is defined as

“use strict”;

If the browser does not support it, it will only be parsed as an ordinary string statement, which will be ignored without any side effects.
If this line of statement is not on the first line, it will be invalid, and the entire script will run in "normal mode".

1.4 Syntax and Behavior Changes

1.4.1 Variables must be declared with var

In normal mode, if a variable is assigned without a declaration, it defaults to a global variable. Strict mode forbids this usage, and global variables must be explicitly declared.

a = 100;
//非严格模式下,输出 a: 100
//严格模式下,a没有声明,抛出一个错误 Error: a is not defined
console.log("a:",a);

1.4.2 Prohibition of using octal numbers

var num4 = 076;//八进制标识 0
//非严格模式下,使用八进制没有任何位置
//严格模式下,不支持八进制 报错SyntaxError: Octal literals are not allowed in strict mode.

1.4.3 Disabling the use of arguments.callee

Inside a function, there are two special objects: arguments and this. Among them, the main purpose of arguments is to save function parameters, but this object also has an attribute called callee, which is a pointer to the function that owns this arguments object.
But in strict mode, it is forbidden to use.
As follows, the recursive call of factorial is realized

function factorial(num){
    
    
    if(num == 1){
    
    
        return 1;
    }else{
    
    
        // return num * factorial(num - 1);//原来阶乘方式
        
        //非严格模式下,使用arguments.callee()指向拥有这个arguments对象的函数
        //严格模式下禁止使用 报错TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
        return num * arguments.callee(num - 1);
     }  
}

1.4.4 Prohibit using delete to delete variables

delete is often used to delete attributes in objects; if you use delete to delete a variable, it can be executed in normal mode, but it will not be deleted successfully; in strict mode, it is forbidden to use it

// 定义变量a
var a = 100;
// 定义window全局对象的变量b
window.b = 200;
// 以上两个都属于全局变量
    
// 删除操作
// 非严格模式下,可以删除window对象的全局变量b,但是不能删除使用var声明的全局变量a,不会报错
// 严格模式下,禁止使用delete删除变量,一旦使用就会报错:SyntaxError: Delete of an unqualified identifier in strict mode
delete a;
delete b;

1.4.5 Prohibit this in custom functions from pointing to window

(function fn(){
    
    
    //非严格模式下,普通函数中的this指向window
    //严格模式下,普通函数中的this不再指向window  返回undefined
	console.log(this);
})();

1.4.6 Create eval scope, namely: block-level scope

In normal mode, Javascript language has two variable scopes (scope): global scope and function scope. Strict mode creates a third scope: the eval scope.
In normal mode, the scope of the eval statement depends on whether it is in the global scope or in the function scope. In strict mode, the eval statement itself is a scope and can no longer generate global variables. The variables it generates can only be used inside eval

eval("var x = 10;");  
 
// 非严格模式下,x为10  
// 严格模式下,x没有声明,抛出一个错误  Error: s is not defined
alert(x); 

任意由eval()创建的变量或函数仍呆在eval()里。然而,你可以通过从eval()中返回一个值的方式实现值的传递:
var result = eval("var a = 10,b = 20;a + b");
// 严格模式与非严格模式下都能正常工作(得到30)
console.log("result:",result);//result: 30

1.4.7 width scope

with(target){} method:
In normal mode: if a tatget object is added, it will treat this object as the top of the scope of the code body to be executed by with, that is, with will change the scope chain.
The scope chain is a structure generated through a very complicated situation. After the scope chain is changed, the system kernel will consume a lot of efficiency to change the scope chain, which will make the program very slow.
Therefore, in ES5 strict mode, the with method can no longer be used.

   "use strict";

    var num = 10;
    var obj = {
    
    
        name:"张三",
        num:100
    }
    fn()
    function fn(){
    
    
        var num = 1000;
        // console.log(num);//1000
        // with(window){
    
    
        //     console.log(num);//10
        // }
        with(obj){
    
    
            console.log(num);//100

            var score = 99;

            console.log(score);//99
        }
        console.log(score);//99
    }
    // console.log(score);//Error: score is not defined  width(){}中声明的不存在的变量的作用域由它所在的那个作用域决定

    // 严格模式下不支持 width(){}  报错  SyntaxError: Strict mode code may not include a with statement 

1.4.8 Objects cannot have attributes with the same name

In normal mode, if an object has multiple properties with the same name, the last assigned property will overwrite the previous value. In strict mode, this is a syntax error (but the program currently cannot detect it).

var obj = {
    
    a:10,a:100}

1.4.9 Functions cannot have parameters with the same name

In normal mode, if the function has multiple parameters with the same name, they can be read with arguments[i]. In strict mode, this is a syntax error.

"use strict";
//严格模式下报错 Error: Duplicate parameter name not allowed in this context
function fn(a,a,b){
    
    
  return;
}

1.4.10 Reserved words

In order to transition to a new version of Javascript in the future, strict mode has added some reserved words: implements, interface, let, package, private, protected, public, static, yield.
Using these words as variable names will throw an error.

//非严格模式下不会报错
//严格模式下报错 Error: Unexpected strict mode reserved word
var let = 10;

In addition, the fifth edition of ECMAscript itself stipulates other reserved words (class, enum, export, extends, import, super), as well as const reserved words added by major browsers, which cannot be used as variable names.

Note: After testing, IE6, 7, 8, and 9 do not support strict mode

2. Provide a global JSON object

Serialization and deserialization concepts:
(1) Serialization: Convert objects in memory into byte sequences for persistence to disk or transmission over the network. The main purpose of object serialization is to transfer and save objects to ensure the integrity and transferability of objects.
Serialization is the conversion of an object into an ordered stream of bytes for transmission over the network or storage in a local file. The serialized byte stream saves the state of the object and related description information. The core function of the serialization mechanism is
the preservation and reconstruction of the object state.
(2) Deserialization: The process of creating an object from a sequence of bytes is called deserialization. The serialized object has nothing to do with the platform, and the serialized byte stream can be deserialized on any platform. After obtaining the serialized byte stream from the file or the network,
according to the object state and description information stored in the byte stream, reconstruct the object through deserialization.

2.1 Serialization of JSON.stringify( ) objects, converting js objects (arrays) to json objects (arrays)

JSON.stringify(obj/arr, callbackfn)
parameters: obj is required; the object to be processed
callbackfn is optional; callback function, there are two parameters in the function as follows:
The first parameter: attribute name
The second parameter: attribute value

// 需求一:对象转JSON串的过程中,将 数字字符串 作为 数字保留
//定义对象
var obj = {
    
    
     a:1,
     b:'2',
     c:{
    
    
        d:3
    }
}
//对象转JSON串 JSON.stringify()
var result = JSON.stringify(obj,function(key,value){
    
    
    // 对value进行判断
    if(typeof value === "string"){
    
    
         // 是字符串数字,通过 正(+)运算符转为纯数值
         return +value;//这里 + 是 正负的正符号 数学运算 转为数值
    }
    return value;
});
console.log(result,"数据类型:",typeof result);//{"a":1,"b":2,"c":{"d":3}} 数据类型: string

2.2 Deserialization of JSON.parse( ) object, convert json object (array) to js object (array)

JSON.parse(json, callbackfn)
parameters: str is required; the json string to be processed
callbackfn is optional; the callback function has two parameters as follows:
the first parameter: attribute name
the second parameter: attribute value

// 需求2:JSON串转对象过程中,将 数字字符串 转为 数字
// 创建JSON串
var jsonStr = '{"a":1,"b":"2","c":{"d":3}}';
// JSON串转对象 JSON.parse()
var result2 = JSON.parse(jsonStr,function(key,value){
    
    
     // 将 数字字符串 转为 数字
     if(typeof value === "string"){
    
    
        return +value;
     }
    return value;
});
console.log(result2,"数据类型:",typeof result2);//a: 1, b: 2, c: {…}} "数据类型:" "object"

Three, ES5 new object features

3.1 Object attribute characteristics

  • The Object.defineProperty((obj,prop,descriptor) method can precisely add or modify properties on an object. This method is used to set a single property attribute
    parameter

    • obj the object on which to define the property
    • prop The name of the property to define or modify
    • descriptor A description of the property defined or modified

    return value object passed to the function

  • The Object.defineProperties(obj, props) method defines new properties or modifies existing properties directly on an object and returns that object.
    parameter

    • obj The object on which to define or modify properties.
    • props An object whose keys represent the names of the properties to be defined or modified, and whose values ​​are objects describing those properties. Each value in props must be a data descriptor or an accessor descriptor

    return value object passed to the function

Note: Object.defineProperties essentially defines all properties corresponding to the enumerable properties of the object obj object

// 在ES3.1中,只要对象能够访问到,就可以任意的去操作该对象,访问对象、添加属性、修改属性和删除属性,如下:
    console.group("ES3对象操作");
    var stu = {
    
    
        name:"张三",
        sex:"男",
        age:23
    }
    console.log("原对象stu:",stu);
    // 添加分数属性
    stu.score = 100;
    console.log("添加分数属性后stu:",stu);
    // 删除年龄属性
    delete stu.age;
    console.log("删除年龄属性后stu:",stu);
    // 修改性别属性
    stu.sex = "女";
    console.log("修改性别属性后stu:",stu);
    console.groupEnd();

    //在ES5中,为对象拓展了一个叫做“特性”的东西,为对象中属性的可访问行进行了限制 如设置属性是否可以被枚举的特性enumerable [ɪ'njʊmərəbl],属性值为布尔值
    console.group("ES5限制枚举特性");
    // 使用for...in 枚举(一一列举)对象的属性
    for(var i in stu){
    
    
        console.log(i);//没有限制枚举的情况下,正常获取对象的每一个属性
    }

    // console.log("====== 开始限制某个独立属性的枚举 ======")

    // // 使用ES5中对象的特性 enumerable限制枚举 属性值设置为false则对象属性不可枚举 默认true可枚举
    // Object.defineProperty(stu,"score",{
    
    
    //     // 设置score属性不可枚举
    //     enumerable:false
    // })
    // for(var i in stu){
    
    
    //     console.log(i);//限制枚举的情况下,不能正常获取对象限制枚举的属性
    // }

    console.log("====== 限制多个属性的枚举 ======")
    
    Object.defineProperties(stu,{
    
    
        "name":{
    
    
            enumerable:false
        },
        "sex":{
    
    
            enumerable:false
        }
    })
    for(var i in stu){
    
    
        console.log(i);//限制枚举的情况下,不能正常获取对象限制枚举的属性
    }
    console.groupEnd();

Summary: The properties in the object can be enumerated by default; but after using the ES5 method to limit the enumeration, the properties after the restricted enumeration cannot be enumerated again

Three types of objects in JS:

  • A native object is an object or class defined by the ECMAScript specification. For example: function object, array object, date object, regular expression object, etc.
  • The host object (host object) is defined by the host environment (web browser) embedded by the js compiler. For example, the HTMLElement object representing the web page structure in the client js is an object created by the host environment. If the objects defined by the host environment can be used directly, we can also treat them as built-in objects.
  • Custom object (user-defined object) Object created by running js.

Two types of attributes in JS:

  • Own property (own property) The property defined directly in the object, which is different from the inherited property.
  • inherited property A property defined in an object's prototype.

Property descriptor object (property description) in JS:
A property descriptor object (property descriptor) is defined in ES5. The object properties have the same names as the properties they describe.

  • value: The value of the attribute.
  • writable: writability, whether the value can be set.
  • enumerable: Enumerability, whether this property will appear when traversing objects.
  • configurable: configurability.

Configure the value through the value attribute:

 // 在ES3.1中,只要对象能够访问到,就可以任意的去操作该对象,访问对象、添加属性、修改属性和删除属性,如下:
    // console.group("ES3对象操作");
    // var stu = {
    
    
    //     name:"张三",
    //     sex:"男",
    //     age:23
    // }
    // console.log("原对象stu:",stu);
    // // 添加分数属性
    // stu.score = 100;
    // console.log("添加分数属性后stu:",stu);
    // // 删除年龄属性
    // delete stu.age;
    // console.log("删除年龄属性后stu:",stu);
    // // 修改性别属性
    // stu.sex = "女";
    // console.log("修改性别属性后stu:",stu);
    // console.groupEnd();

    //在ES5中,为对象的属性配置值
    console.group("ES5添加属性的值");
    // 创建一个空对象
    var stu = {
    
    }
    // ES5方法为空对象添加属性和属性值
    Object.defineProperty(stu,'name',{
    
    
        // 配置值 添加属性值
        value:"张翠花"
    })
    // 访问对象  通过这种方式添加的属性
    console.log("stu:",stu);//stu: {name: "张翠花"}
    // 删除属性  不能使用 delete 删除配置的属性
    delete stu.name;
    console.log("stu:",stu);//stu: {name: "张翠花"}
    // 访问属性  可以访问配置的属性
    console.log("stu.name:",stu.name);//stu.name: 张翠花
    // 修改属性  不可以使用 obj.att  或  obj[att]方 式修改属性
    stu.name = "张无忌";
    // 访问属性  可以访问配置的属性
    console.log("stu.name:",stu.name);//stu.name: 张翠花
    //枚举属性   不可以被枚举
    for(var i in stu){
    
    
        console.log(i);
    } 
    console.groupEnd();

    // ES5,修改对象属性
    var obj = {
    
    type:"未知"};
    console.log(obj.type);//未知
    Object.defineProperty(obj,"type",{
    
    
        value:"狗"
    });
    console.log(obj.type);//狗
    obj.type = "猫";
    console.log(obj.type);//猫
    delete obj.type;
    console.log(obj.type);//undefined

    /*
    * 总结:1. 当一个对象中没有任何原有属性,通过特性的方式 Object.definePeoperty方式添加的属性,里面属性的所有特性都是false:
    *        即:通过这种方式添加的属性不能够删除、修改和枚举。
    *     2. 如果一个对象中天生自带某个属性,此时对象属性的所有特性属性值为true:
    *        即:只要对象能访问到,不管什么方式,都可以进行任意的操作
    */

Configure writability via the writable feature

	// 创建一个对象
    var obj = {type:"未知"}

    // 将对象的属性type设置为不可写特性(即:不可修改)
    Object.defineProperty(obj,"type",{
        // 设置属性是否可写  true默认可写  false不可写
        writable:false
    })
    
    console.log("修改前属性type:",obj.type);//修改前属性type: 未知

    // 尝试使用普通的方式进行修改  结果不可修改
    obj.type = "猫";
    
    console.log("修改后属性type:",obj.type);//修改后属性type: 未知

Configure enumerability via enumerable

// 创建一个对象
    var obj = {
        type:"未知",
        color:"白色"
    }

    // 默认情况下,对象的属性可以被枚举
    for(var i in obj){
        console.log(i);
    }

    // 设置属性color特性 不可枚举
    Object.defineProperty(obj,"color",{
         // 默认true可被枚举  设置false不可被枚举
        enumerable:false
    })

    // 设置color不可枚举后,尝试枚举,color不再出现
    for(var i in obj){
        console.log(i);
    }

Configure related configuration through configurable

// 创建一个对象
    var obj = {
        type:"未知",
        color:"白色"
    }

    console.log(obj.color)

    // 设置属性特性 配置 value值 writeable可写性
    Object.defineProperty(obj,"color",{
        // 配置属性的value值
        value:"黄色",
        // 不可修改
        writable:false,
        // 设置是否重复配置相关特性  默认false可重复配置,设置true不可以重复配置
        configurable:false
    })

    console.log(obj.color);//白色

    // 重复修改 可写特性 的值
    Object.defineProperty(obj,"color",{
        // 配置属性的value值
        value:"黄色",
        // 可修改
        writable:true
    })

    console.log(obj.color);//黄色

    // 修改obj中的属性
    obj.color = "黑色";

    console.log(obj.color);//如果 writeable为true,则可以通过普通方式修改属性值;否则不可以

    // 总结:设置属性特性configurable为false的情况下,不能重复配置相关特性,否则报错 TypeError: Cannot redefine property: color

Storer set and getter get

<body>
<h2>单项数据绑定:通过修改JS中的数据,页面呈现最新修改的数据信息。这是一种映射关系,把JS数据的变化映射到DOM结构上</h2>
<div id="box">数据单项绑定呈现位置</div>
<input type="text" id="ipt">
</body>
<script src="./js/jquery-1.12.3.min.js"></script>
<script>
    // 创建对象
    // var obj = {
    
    
    //     des:"把Model的变化映射到DOM结构上"
    // }

    // 获取元素
    // var box = document.getElementById("box");

    // // 设置元素的内部文本
    // box.innerHTML = obj.des;

    // 普通的方式,修改对象的值,查看页面DOM数据变化
    // obj.des = "新的数据";//页面不会发生改变,除非通过innerHTML重新写入

    // 通过set方法设置单项绑定
    // Object.defineProperty(obj,'des',{
    
    
    //     //赋值器
    //     set:function(value){
    
    
    //         // 当设置或修改新的值时,将最新的值输出到页面
    //         box.innerHTML = value;
    //         // 备用属性赋值
    //         this.oDes = value;
    //     },
    //     // 取值器
    //     get:function(){
    
    
    //         return this.oDes;
    //     }
    // });

    // 再次修改以下值试试
    // obj.des = "新的值";//发现页面内容更新了


    // 现在我们做这样一个修改,页面添加一个输入框,随着输入框内容的输入,上面呈现输入框中的内容,修改如下:
    // 创建对象
    var obj = {
    
    
        des:"把Model的变化映射到DOM结构上"
    }

    // 获取元素
    var box = document.getElementById("box");
    var ipt = document.getElementById("ipt");

    // 设置元素的内部文本
    box.innerHTML = obj.des;
    Object.defineProperty(obj,'des',{
    
    
        //赋值器
        set:function(value){
    
    
            // 当设置或修改新的值时,将最新的值输出到页面
            box.innerHTML = value;
            // 备用属性赋值
            this.oDes = value;
        },
        // 取值器
        get:function(){
    
    
            return this.oDes;
        }
    });

    // 新的值来自于页面输入框 触发正在输入事件
    // ipt.oninput = function(){
    
    
    //     if(this.value === ""){
    
    
    //         box.innerHTML = "把Model的变化映射到DOM结构上";
    //     }else{
    
    
    //         obj.des = this.value;
    //     }
    // }
    
    // 含有输入法时,不能检测中文,改造并使用jQuery(使用js也可)如下:

    /**
    * 拓展:实现中文输入法下,仅在选词后触发input事件
    * 描述:在使用oninput监控输入框内容变化时,我们期望仅在value值变化时,才触发oninput事件,而在中文输入下,未选词时的按键也会触发oninput事件。
    * 两个事件:
    *   compositionstart事件
    *   compositionend事件
    * 实现方式:使用一个变量表示拼写状态,在oninput事件中判断是否在拼写状态,当拼写状态结束,继续执行下一步操作。
    * 代码示例如下:
    **/
    // 定义是否开启输入法的开关 默认关闭
    var flag = false;
    //oninput在oncompositionend之前执行,需加定时器
    ipt.oninput = function(){
    
    
        this.addEventListener('compositionstart',function(){
    
    //中文开始书写
            flag = true;//检测到中文输入法开启,设为true
        })
        this.addEventListener('compositionend',function(){
    
    //中文书写完毕,选取文字完毕
            flag = false;//输入完毕,设置false
        })
        setTimeout(function() {
    
    
            if(!flag) {
    
    //保证输入法没有开启也能正常获取数据
                if(ipt.value === ""){
    
    
                    box.innerHTML = "把Model的变化映射到DOM结构上";
                }else{
    
    
                    obj.des = ipt.value;
                }
            }
        },0);
    }
</script>

Application of all properties of the object:

  // 创建一个对象
    var obj = {
    
    
        name:"张三",
        age:25
    }

    // 设置多属性特性value
    Object.defineProperties(obj,{
    
    
        // 设置属性name的特性
        name:{
    
    
            // 配置值 设置或修改值
            value:"张三丰",
            // 是否可写配置 设置值为false后不可以再通过普通方式修改值
            writable:false,
            // 是否可枚举配置 设置值为false后 不可以枚举属性
            enumerable:false,
            // 是否可配置设置,设置为false后不能使用任何方式重复修改设置
            configurable:false
        },

        // 设置属性age的特性
        age:{
    
    
            // 存值器
            set:function(value){
    
    
                this.oAge = value;
            },
            // 取值器
            get:function(){
    
    
                return this.oAge;
            },
            // 设置是否可枚举  设置false后,age属性不再被获取,只显示备用属性
            enumerable:false,
            // 注意:一旦设置set/get方法就是设置了设置值或修改值的配置,
            // 一旦设置了set特性方法,就不能再设置相同功能的特性 writeable 与 value,否则配置冲突报错
            // 设置是否可写
            // writable:false,
            // 配置新的值
            // value:"张君宝"
        }
    })

    // 尝试修改obj中的属性
    obj.name = "张翠华";
    obj.age = 23;

    console.log(obj)

    // 尝试枚举
    for(var i in obj){
    
    
        console.log(i,obj[i])
    }

3.2 Prototype Expansion

ES5 extends several methods for prototypes:

  1. The isPrototypeOf(obj) method is used to determine whether the prototype object is the prototype of the parameter instance object
    Parameter instantiation object
    Note that in the process of searching, the entire prototype chain will be searched; that is, the prototype of the prototype is also the prototype of the instantiated object
  2. The Object.setPrototypeOf(obj,prototype) method is used to set the prototype of an instance object. The
    parameter obj instantiated object
    prototype is the new prototype object to be set for the previously instantiated object (can be null or an object)
  3. The Object.getPrototypeOf(obj)
    parameter instantiates the object

Before ES5, the instantiated object obtained the prototype object through the proto
attribute; in ES5, the statement beginning with __ is not recommended, so the getPropertyOf() method is provided to obtain the prototype object of the object

<body>
<ul>
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>
</body>
<script>
    // 获取类数组对象
    var lis = document.getElementsByTagName("li");

    // 定义数组
    var arr = [10,20,30,40];

    // 自定义对象
    var obj = {
    
    name:"张三"}

    // 查看Array.prototype这个原型是哪个实例化对象的原型
    console.log(Array.prototype.isPrototypeOf(lis));//false
    console.log(Array.prototype.isPrototypeOf(obj));//false
    console.log(Array.prototype.isPrototypeOf(arr));//true

    // 查找过程中,会查找整个原型链
    console.log(Object.prototype.isPrototypeOf(lis));//true
    console.log(Object.prototype.isPrototypeOf(obj));//true
    console.log(Object.prototype.isPrototypeOf(arr));//true

    // 获取实例化对象 arr 的原型对象
    // 原始方式
    console.log(arr.__proto__);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
    // ES5方式
    console.log(Object.getPrototypeOf(arr));//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
    // 对比
    console.log(arr.__proto__ === Object.getPrototypeOf(arr));//true

   
    // 设置实例化对象 arr 的原型对象  可以为null 也可以是一个对象  会修改整个原型链
    Object.setPrototypeOf(arr,null);
    console.log(Object.getPrototypeOf(arr));//null

    Object.setPrototypeOf(arr,{
    
    a:10});
    console.log(Object.getPrototypeOf(arr));//{a:10}

    // 构造函数的原型不变  只是实例化对象原型指向改变
    console.log(Array.prototype);//[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
</script>

3.3 Cancel object extensibility

The Object.preventExtensions(obj) method is used to cancel the extensibility of the object
. Object.isExtensible(obj) judges whether the object is extensible.
The return value is a Boolean value, which returns true and the object can extend the attributes. Returns false. The object cannot extend the attributes

Note: When an object is cancelled, the object can no longer extend attributes, but attributes can be modified and deleted

var obj = {
    
    
        a:1,
        b:2
    }

    console.log("冻结前对象:",obj);

    // 取消对象拓展
    Object.preventExtensions(obj);

    // 拓展属性
    obj.c = 3;

    // 删除属性
    delete obj.a;

    // 修改属性值
    obj.b = 22;

    // 判断对象是否可拓展
    console.log(Object.isExtensible(obj));//true

    console.log("冻结后并操作属性后的对象:",obj);

3.4 Closed objects

  • Object.seal(obj) closes the properties of the object
  • Object.isSealed(obj) determines whether the object property is sealed
    Return value Boolean, returns true if the object is sealed returns false the object is not sealed

Note: When an object is closed, attributes cannot be expanded and deleted, but attributes can be modified.

var obj = {
    
    
        a:1,
        b:2
    }

    console.log("封闭前对象:",obj);

    // 封闭对象
    Object.seal(obj);

    // 拓展属性
    obj.c = 3;

    // 删除属性
    delete obj.a;

    // 修改属性值
    obj.b = 22;

    // 判断对象是否被封闭
    console.log(Object.isSealed(obj));//true

    console.log("封闭后并操作属性后的对象:",obj);

3.5 Freezing objects

The Object.freeze(obj) method is used to freeze the properties of the object.
The Object.isFrozen(obj) method is used to determine whether the object properties are frozen.
Return value A boolean value returns true and the object is frozen, and returns false and the object is not frozen

Note: When an object is frozen, the properties of the object cannot be expanded, modified or deleted;

var obj = {
    
    
        a:1,
        b:2
    }

    console.log("冻结前对象:",obj);

    // 冻结对象
    Object.freeze(obj);

    // 拓展属性
    obj.c = 3;

    // 删除属性
    delete obj.a;

    // 修改属性值
    obj.b = 22;

    // 判断对象是否被冻结
    console.log(Object.isFrozen(obj));//true

    console.log("冻结后并操作属性后的对象:",obj);

3.6 Object.create() New way to create objects

The Object.create(proto, [propertiesObject]) method creates a new object using an existing object as a prototype for the newly created object.
parameter

  • proto The object that should be the prototype of the newly created object. can be null
  • propertiesObject optional. Specifies the property descriptor to add to the newly created object, along with the corresponding property name. These properties correspond to the second argument of Object.defineProperties() to the properties of the object properties.

Returns a new object with the specified prototype object and properties.

// 学过的创建对象的方式
    // var obj = {};
    // var obj1 = new Object();
    // var obj2 = Object();

    // ES5新增创建一个空对象  第一个参数新创建对象的原型设置为null
    // var obj3 = Object.create(null);
    // console.log(obj3)

    //使用Object.create() 来创建一个对象,第一个参数原型对象为一个常量对象
    // var obj = Object.create({
    
    
    //     sayHi:function(){
    
    
    //         console.log("Hello");
    //     }
    // })

    // 第一个参数为空,第二个参数为 要创建对象的空对象的属性特性描述(类似于Object.defineProperty()设置的对象特性)
    // var obj = Object.create(null,{
    
    
    //     name:{
    
    
    //         // 配置值
    //         value:"张三",
    //         // 配置是否可写
    //         writable:false,
    //         // 配置是否可枚举
    //         enumerable:false
    //     },
    //     age:{
    
    
    //         // 配置值
    //         value:10,
    //          // 配置是否可写
    //          writable:false,
    //     }
    // })
    // console.log(obj);
    // console.log(obj.name);
    // // 通过这种对象特性的方式创建的对象,默认属性不能被删除 修改
    // obj.name = "haha";
    // delete obj.age;
    // console.log(obj);
    // console.log(obj.name);


    // 创建一个对象,并能继承另外一个对象的方法;将一个对象作为另外一个对象的原型
    // 创建需要的原型对象
    var prototype = {
    
    
        sayHi:function(){
    
    
            console.log("Hello");
        }
    }

    // 创建需要的特性属性对象
    var options = {
    
    
        name:{
    
    
            // 配置值
            value:"张三",
            // 配置是否可写
            writable:false,
            // 配置是否可枚举
            enumerable:false
        },
        age:{
    
    
            // 配置值
            value:10,
             // 配置是否可写
             writable:false,
        }
    }

    // 两者组合创建对象
    var obj = Object.create(prototype,options);

    console.log(obj)//查看原型
    obj.sayHi();

利用Object.create()完善继承
// 定义父类
    function People(name,sex,age){
    
    
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    // 原型中定义方法
    People.prototype.sayHi = function(){
    
    
        return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
    }

    People.prototype.sayHello = function(){
    
    
        return "Hello";
    }

    // 定义子类
    function Student(name,sex,age,score){
    
    
        // applay实现继承(改变调用对象
        People.apply(this,arguments);

        // 定义子类拓展的属性
        this.score = score;
    }

    // var p = new People();
    // delete p.name;
    // delete p.sex;
    // delete p.age;

    // 子类继承父类中的方法 必须要使用原型继承 将子类的原型指向父类的实例
    // Student.prototype = new Student();

    // 使用Object.create()优化继承
    Student.prototype = Object.create(People.prototype);

    // 原型继承会造成结构的紊乱,将原型对象的构造函数手动改回到Student
    Student.prototype.constructor = Student;

    // 实例化对象
    var s = new Student("张三","男",23,100);

    // 调用父类原型中的方法
    console.log(s.sayHi());

    /*
    * 原型继承,子类的原型就是父类的实例,这种方式会在子类的原型中多出几个无用的属性
    * 此时,会在子类的原型中多出几个属性:name:undefined,age:undifined,sex:undefined
    * 如果不考虑寄生组合继承这种方式进行优化,ES5还提供了Object.create()方法来优化
    **/

Encapsulate and implement the Object.create() method by yourself

// 定义父类
    function People(name,sex,age){
    
    
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    // 原型中定义方法
    People.prototype.sayHi = function(){
    
    
        return "姓名:" + this.name + ",性别:" + this.sex + ",年龄:" + this.age;
    }

    People.prototype.sayHello = function(){
    
    
        return "Hello";
    }

    // 定义子类
    function Student(name,sex,age,score){
    
    
        // applay实现继承(改变调用对象
        People.apply(this,arguments);

        // 定义子类拓展的属性
        this.score = score;
    }

    // 取消Object.create方法
    Object.create = null;
    // 重新自定义 create 方法,实现相同的功能
    Object.create = function(prototype){
    
    
        // 定义一个构造函数
        var F = function(){
    
    

        }

        // 将F的原型指向传入的原型
        F.prototype = prototype;

        // 返回F的实例
        return new F();
    }

    // 使用Object.create方法实现继承
    Student.prototype = Object.create(People.prototype);

    // 实例化对象
    var s = new Student("张三","男",23,100);
    console.log(s.sayHi());

Guess you like

Origin blog.csdn.net/qq_39335404/article/details/130480118
Recommended