JavaScript面向对象编程

news2024/11/25 20:47:30

在这里插入代码片## 1. 构造函数和new命令

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <!-- 
        构造函数:
            1. 典型的面向对象编程语言(比如 C++ 和 Java),都有“类”(class)这个概念。
               所谓“类”就是对象的模板,对象就是“类”的实例。但是,JavaScript 语言的对象体系,
               不是基于“类”的,```而是基于构造函数(constructor)和原型链(prototype)```。

            2. ```JavaScript 语言使用构造函数(constructor)作为对象的模板。```
               所谓”构造函数”,就是专门用来生成实例对象的函数。它就是对象的模板,
               描述实例对象的基本结构。```一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。```

            3. 构造函数就是一个普通的函数,但是有自己的特征和用法。

            4. ```为了与普通函数区别,构造函数名字的第一个字母通常大写。```

            5.构造函数的特点有两个:
                (1) 函数体内部使用了this关键字,代表了所要生成的对象实例; 
                (2) 生成对象的时候,必须使用new命令; 

            6. new命令本身就可以执行构造函数,所以后面的构造函数可以带括号,也可以不带括号。
              ```下面两行代码是等价的,但是为了表示这里是函数调用,推荐使用括号。```
              var v = new Vehicle();  // 推荐的写法
              var v = new Vehicle;    // 不推荐的写法
     -->
</head>

<body>
    <script>
        /* 
            1. 如果忘了使用new命令,直接调用构造函数会发生什么事???
                这种情况下,构造函数就变成了普通函数,并不会生成实例对象; 
                this这时代表全局对象,将造成一些意想不到的结果; 
                因此,应该非常小心,避免不使用new命令、直接调用构造函数; 
            2. 为了保证构造函数必须与new命令一起使用:
                (1) 构造函数内部使用严格模式,即第一行加上use strict, 这样的话,一旦忘了使用new命令,直接调用构造函数就会报错; 
                    (由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用会报错;
                     JavaScript 不允许对undefined添加属性)
                        function test(foo, bar){
                            'use strict';
                            this._foo = foo;
                            this._bar = bar;
                        }
                    test();    // TypeError: Cannot set property '_foo' of undefined
                (2) 另一个解决办法,构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象; 
        */
        var Vehicle = function () {
            console.log(this);
            if (!(this instanceof Vehicle)) {
                return new Vehicle();   // new
            }
            this.price = 1000;
        };
        // var v = Vehicle();       // 执行2次log
        new Vehicle();              // 执行1次log
    </script>
</body>

</html>

2. new命令原理

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        使用new命令时,它后面的函数依次执行下面的步骤。
            1. 创建一个空对象,作为将要返回的对象实例; 
            2. 将这个空对象的原型,指向构造函数的prototype属性; 
            3. 将这个空对象赋值给函数内部的this关键字; 
            4. 开始执行构造函数内部的代码; 
        也就是说,构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。
        构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。
     -->
</head>

<body>
    <script>
        /*
            1. 如果构造函数内部有return语句:
                (1) return后面跟着一个对象,new命令会返回return语句指定的对象; 
                (2) 否则,就会不管return语句(将会被忽略),返回this对象; 
            2.  另一方面,如果对普通函数(内部没有this关键字的函数)使用new命令,则会返回一个空对象; 
        */

        // (1)构造函数Vehicle的return语句返回的是一个数值; 
        //  这时,new命令就会忽略这个return语句,返回“构造”后的this对象。
        var Vehicle = function () {
            this.price = 1999;
            return 1000;
        };
        var obj = new Vehicle();
        console.log((new Vehicle()) === 1000); // false


        // (2)但是,如果return语句返回的是一个跟this无关的新对象,
        //  new命令会返回这个新对象,而不是this对象。这一点需要特别引起注意; 
        var Animal = function () {
            this.animal = 'cat';
            return {
                name: 'Zhang'
            };
        }
        var object = new Animal();
        console.log(object); // {name: "Zhang"}


        // (3) getMessage是一个普通函数,返回一个字符串; 
        // 对它使用new命令,会得到一个空对象。这是因为new命令总是返回一个对象,要么是实例对象,要么是return语句指定的对象;
        // 本例中,return语句返回的是字符串,所以new命令将忽略该语句, 直接返回一个空对象; 
        function getMessage() {
            return 'HelloWorld'; //将会被忽略
        }
        var msg = new getMessage();
        console.log(typeof msg); //{} object
    </script>


    <script>
        /*
            3. 函数内部的new.target属性 :
                (1) 函数内部可以使用new.target属性; 
                (2) 如果当前函数使用了new命令调用,new.target指向当前函数本身,否则为undefined; 
                (3) 使用这个属性,可以判断函数调用的时候,是否使用new命令; 
        */ 
        function test() {
            console.log(new.target === test);
        }
        test();         // false
        new test();     // true

        function fun() {
            if (!new.target) {
                throw new Error('请使用new命令调用!');
            }
        }
        fun();
    </script>

    <!-- Object.create() 创建实例对象 -->
    <script>
        /*
            4. 构造函数作为模板,可以生成实例对象; 但是,有时拿不到构造函数,只能拿到一个现有的对象; 
               我们希望以这个现有的对象作为模板,生成新的实例对象; 这时就可以使用Object.create()方法; 
               该函数对于复杂类型(数组, 对象)实行浅拷贝; 
        */
        var person = {
            name: 'ZhangSan',
            age: 38,
            sing: function () {
                console.log('i like sing!');
            },
            books: {
                firstBook: '三国演义',
                secondeBook: '水壶传'
            },
            arr: [1, 2, 3, 4]
        };
        var _person = Object.create(person);
        person.books.firstBook = '红楼梦';
        person.arr = ['one', 'two', 'three', 'four'];
        // ps: 对于复杂数据类型来说, 是浅拷贝
        console.log(_person.books.firstBook);   // 红楼梦
        console.log(_person.arr);               // ["one", "two", "three", "four"]
    </script>
</body>

</html>

3. prototype-1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        构造函数中的  原型对象:
            构造函数通过原型分配的函数时所有对象所共享的; 
            ```JavaScript规定, 每一个构造函数都有一个prototype属性, 指向另一个对象;```
            注意:prototype就是一个对象, 这个对象的所有属性和方法, 都会被构造函数所拥有; 
            ```我们可以把那些不变的方法, 直接定义在prototype原型对象上面, 这样所有对象实例就都可以共享这些方法;```
            prototype: 原型, 也称原型对象; 
            ```原型对象上面存在着许许多多的方法;```
     -->

     <!-- 
         ```JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享; ```
         ```也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系; ```
        ```下面,先看怎么为对象指定原型。JavaScript 规定,每个函数都有一个prototype属性,指向一个对象; ```
      -->
</head>

<body>
    <script>
        function Father(name, age) {
            this.name = name;
            this.age = age;
            this.sing = function() {
                console.log('sing a song!');
            }
        }
        console.dir(Father); 
        
        var obj1 = new Father('Zhang', 13); 
        var obj2 = new Father('Li', 32); 

        console.log(obj1.name === obj2.name);   // false
        console.log(obj1.sing === obj2.sing);   // false

        
        // 在原型对象上添加方法
        Father.prototype.say = function() {
            console.log('I am father!');
        }
        console.log(obj1.say === obj2.say);     // true

    </script>
</body>

</html>

4. prototype-2

<!DOCTYPE html> 
<html lang="en"> 

<head> 
    <meta charset="UTF-8"> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0"> 
    <title>Document</title> 
    <!-- 
        大部分面向对象的编程语言,都是通过“类”(class)来实现对象的继承; 
        JavaScript 语言的继承则是通过“原型对象”(prototype); 
    --> 
     <!-- 
         1. prototype: 每个函数都有一个prototype属性,指向一个对象; 
                a. 对于普通函数来说, 该属性基本无用; 
                b. 对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型; 
                c. ``````实例对象可以视作从原型对象(prototype)衍生出来的子对象``````; 
      -->
</head>

<body>
    <script>
        /* 
            1. 构造函数: 
                (1) JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板; 
                    实例对象的属性和方法,可以定义在构造函数内部; 
        */
        function Cat(name, color) {
            this.name = name;
            this.color = color;
            this.move = function () {
                console.log('喵喵');
            };
        };
        var cat1 = new Cat('大毛', '白色');
        var cat2 = new Cat('二毛', '黑色');
        console.log(cat1.move === cat2.move); // false
        /*
            上面代码中,cat1和cat2是同一个构造函数的两个实例,它们都具有move方法; 
            由于move方法是生成在每个实例对象上面,所以两个实例就生成了两次; 
            也就是说,每新建一个实例,就会新建一个move方法; 
            这既没有必要,又浪费系统资源,因为所有move方法都是同样的行为,完全应该共享; 
            ===> 这个问题的解决方法,就是 JavaScript 的原型对象(prototype); 
        */
        console.log('----------');
    </script>

    <script>
        /* 
            2. prototype(原型对象) 属性的作用:  
               (1) JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享; 
                   也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系; 
               (2) 下面,先看怎么为对象指定原型。JavaScript规定,每个函数都有一个prototype属性,指向一个对象; 
                        function fun() {}
                        console.log(typeof fun.prototype);      // 'object'
                        上面代码中,函数fun默认具有prototype属性,指向一个对象; 
                        a. ```对于普通函数来说,该属性基本无用; ```
                        b. ```但是,对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型; ```
        */
        function Animal(name) {
            this.name = name;
        }; 
        Animal.prototype.color = 'white'; 
        Animal.prototype.player = 'ball'; 
        Animal.prototype.show = function () {} 
        Animal.prototype.display = function () {} 

        var Cat1 = new Animal('大毛'); 
        var Cat2 = new Animal('二毛'); 
        console.log(Cat1.color);    // 'white' 
        console.log(Cat2.color);    // 'white' 
        console.dir(Animal); 
        console.dir(Cat1); 
        /*
            上面代码中,构造函数Animal的prototype属性,就是实例对象cat1和cat2的原型对象; 
            原型对象上添加一个color属性,结果,实例对象都共享了该属性; 
            ```原型对象的属性不是实例对象自身的属性。只要修改原型对象,变动就立刻会体现在所有实例对象上; ```
            这是因为实例对象其实没有color属性,都是读取原型对象的color属性; 
            ```也就是说,当实例对象本身没有某个属性或方法的时候,它会到原型对象去寻找该属性或方法。这就是原型对象的特殊之处; ```
            ```当然如果实例对象自身就有某个属性或方法,它就不会再去原型对象寻找这个属性或方法; ```
            ``````总结一下,原型对象的作用,就是定义所有实例对象共享的属性和方法; ``````
            这也是它被称为原型对象的原因, ``````而实例对象可以视作从原型对象衍生出来的子对象``````; 
        */
        console.log('----------');
    </script>

    <script>
        /*
            3. constructor属性: prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数; 
                (1)  function fun() {}
                     console.log(fun.prototype.constructor === fun);  // true 
                (2)  作用:可以得知某个实例对象,到底是由哪个构造函数产生的; 
        */
        function Person() {}
        var p1 = new Person();
        console.log(p1);
        console.dir(p1);
        console.log(p1.constructor === Person);                         // true
        console.log(p1.constructor === Person.prototype.constructor);   // true
        console.log(p1.hasOwnProperty(
        'constructor'));    // false (p1自身没有constructor属性, 该属性其实是读取原型链上面的Person.prototype.constructor属性;)
        console.log(Person.prototype === p1.__proto__);                 // true


        // 
        console.log('------------');
        function callback() {};
        var Call = new callback();
        console.log(Call);
        console.log(Call.constructor === callback);     // true 
        console.log(Call.constructor === RegExp);       // false 
        // 上面代码中,constructor属性确定了实例对象Call的构造函数是callback,而不是RegExp; 
    </script>
</body>

</html>

5. __proto__

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        1. 对象原型 __proto__:
            对象都会有一个属性__proto__, 指向构造函数的原型对象(prototype), (首先明确: prototype是构造函数constructor的一个属性)
            之所以我们对象可以使用构造函数prototype原型对象的属性和方法, 就是因为有对象原型__proto__的存在; 
        
        2. __proto__对象原型 和 prototype原型对象是等价的; 
        3. __proto__对象原型的意义就在于为对象的查找机制提供一个方向, 或者说一条路线, 但是它是一个非标准属性, 
            因此实际开发中, 不能使用这个属性, 它只是内部指向原型对象 prototype; 
            __proto__存在的目的就是为了让我们得到prototype对象; (个人)
            __proto__用来标识实例对象所继承的原型; 

        4. 区别:  
            a. prototype: 是构造函数才有的属性; (存在于函数中)
            b. __proto__:是每个对象都有的一个属性; 
            c. prototype 和 __proto__都是一个对象; 
            d. person.__proto__ === Person.prototype; 
     -->
</head>

<body>
    <script>
        function Father(name, age) {
            this.name = name;
            this.age = age;
            this.sing = function () {
                console.log('sing a song!');
            }
        }
        Father.prototype.say = function () {
            console.log('I am father!');
        }
        var father = new Father('Zhang', 21);
        
        console.log(Father.prototype === father.__proto__);    // true 


        // 打印一下三句话, 就可以看出了
        console.log(father); 
        console.log(Father.prototype); 
        console.log(father.__proto__); 
        console.dir(Father);       

        // 为什么father1 可以访问say()函数呢 ???
            // 方法的查找规则: 首先查看father对象自身有没有 say()方法, 如果有就调用; 
            // 如果没有say()方法, 那么因为__proto__的存在(father.__proto__ === Father.prototype), 就会去构造函数的原型对象prototype身上去查找say()方法; (console.dir(Father))
            // 记住: __proto__ === prototype
        father.say();
    </script>
</body>

</html>

6. constructor属性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        1. 原型对象(prototype) 和 对象原型(__proto__)里面都有一个constructor属性, 
           constructor 我们称为构造函数, 因为它指向构造函数本身; 
        2. constructor 主要用于记录该对象引用哪个构造函数, 它可以让原型对象重新指向原来的构造函数; 
     -->
</head>

<body>
    <script>
        function Father(name, age) {
            this.name = name;
            this.age = age;
            this.sing = function () {
                console.log('sing a song!');
            }
        }
/***********************************************************************************************/
        /* 
            以下两句相当于是在原型对象身上添加了两个方法; 
            此时执行  ```打印```语句
                前两句:里面存在constructor构造函数这一属性; 
                后两句:将会打印出构造函数Father; 
        */
       /*
        Father.prototype.say = function () {
            console.log('I am father!');
        }
        Father.prototype.dance = function () {
            console.log('I am father-dance!');
        }
    */
/***********************************************************************************************/
        /* 
            以下话语相当于直接覆盖了原先的原型对象; (该话语相对于上面的话语更为清晰)
            此时执行 ```打印```语句
                前两句:里面将不存在constructor构造函数这一属性; (在不加constructor属性的情况之下)
                后两句:将会打印出 ƒ Object() { [native code] }; 
            ```十分注意```: 如果我们是给原来的原型对象直接赋值对象了, 则此时必须手动的利用prototype.constructor属性指向原来的构造函数; 
        */
        Father.prototype = {
            constructor: Father,        // 手动指向原来的构造函数
            say: function () {
                console.log('I am father!');
            },
            dance: function () {
                console.log('I am father-dance!');
            }
        }
/***********************************************************************************************/
        // ```打印```
        var father = new Father('Zhang', 21);
        console.log(Father.prototype);                  
        console.log(father.__proto__);
        console.log(Father.prototype === father.__proto__);                             // true

        console.log(Father.prototype.constructor);     
        console.log(father.__proto__.constructor);
        console.log(Father.prototype.constructor === father.__proto__.constructor);     // true
    </script>
</body>

</html>

7. 原型链

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        1. JavaScript 规定,所有对象都有自己的原型对象(prototype); 
           一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型; 
           因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……

        2. 如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性; 
           也就是说,所有对象都继承了Object.prototype的属性; 
           这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的; 

        3. 那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null; 
           null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null; 

        4. 读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找; 
           如果直到最顶层的Object.prototype还是找不到,则返回undefined; 
           如果对象自身和它的原型,都定义了一个同名属性,那么优先读取对象自身的属性,这叫做“覆盖”(overriding); 

        5. 注意,一级级向上,在整个原型链上寻找某个属性,对性能是有影响的; 
           所寻找的属性在越上层的原型对象,对性能的影响越大。如果寻找某个不存在的属性,将会遍历整个原型链; 
     -->
</head>

<body>
    <script>
        function Star(name, age) {
            this.name = name;
            this.age = age;
        }
        Star.prototype.dance = function () {
            console.log('dancing!');
        }
        var LDH = new Star('ldh', 24);
        console.log(LDH);
        
        //只要是对象,就有__proto__属性,指向原型对象 
        console.dir(Star);              //构造函数
        console.log(Star.prototype);    //原型对象
        console.log(Star.prototype.__proto__);
        console.log(Star.prototype.__proto__ === Object.prototype);     // true
        console.log(Object.prototype.__proto__);                        // null
    </script>
</body>

</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8. JS成员查找机制

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        1. 当访问一个对象的属性(包括方法)时, 首先查找这个对象自身有没有该属性; 
        2. 如果没有就查找它的原型对象(也就是student.__proto__指向的Student.prototype原型对象); 
        3. 如果还没有就查找原型对象的原型对象(Object的原型对象); 
        4. 以此类推一直找到Object为止(null); 
        5. ``````实例对象可以视作从原型对象(prototype)衍生出来的子对象``````; 
        /*
            举例说明:
                比如:person1.valueOf()
                a. 浏览器首先检查,person1对象是否具有可用的valueOf()方法; 
                b. 如果没有,则浏览器检查person1对象的原型对象(即Person构造函数的prototype属性所指向的对象)是否具有可用的valueof()方法; 
                c. 如果也没有,则浏览器检查Person()构造函数的prototype属性所指向的对象的原型对象(即Object构造函数的prototype属性所指向的对象)是否具有可用的valueOf()方法; 
                d. 如果还是没有, 那么就是undefined的了;
        */
     -->
</head>

<body>
    <script>
        function Father(name, age) {
            this.name = name;
            this.age = age;
        }
        
        var obj = new Father('XingWei', 23);

        Object.prototype.sex = '女-Object';
        Father.prototype.sex = '男-Father';
        obj.sex = '中性-实例对象'; 

        console.log(obj.sex);


        console.log(obj.__proto__  === Father.prototype);               // true
        console.log(obj.__proto__.__proto__ === Object.prototype);      // true
        console.log(Father.prototype.__proto__ === Object.prototype);   // true
        console.log(Object.prototype.__proto__ === null);               // true

        console.log(obj);
        console.log(Father.prototype.__proto__);
        /*
            解析:
                0. 首先我们明确一点:我们是通过实例对象的__proto__属性去得到prototype的(两者等价); 
                1. 首先将在obj对象自身查找sex属性, 如果有就打印出来; 
                2. 否则查找obj对象的原型对象, 怎么查找?通过obj.__proto__属性, 
                ```它指向(等价)Father.prototype```, 也就是在Father.prototype上查找sex, 如果有就打印出来; 
                3. 否则就查找原型(Father.prototype)的原型对象, 怎么查找?通过Father.prototype.__proto__属性(实际上是Object.prototype), 
                ```它指向Object.prototype```, 此时就在Object.prototype上查找sex, 如果有就打印出来; 
                4. 否则继续查找原型(Object.prototype)的原型对象, 怎么查找?通过Object.prototype.__proto__属性(实际是null), 
                ```实际上到第三步就停止了, 如果没有找到就是undefined了; 
        */

        /*
            console.log(obj);       // 打印obj实例对象
            打印结果:
                >Father {name: "XingWei", age: 23, sex: "中性-实例对象"}
                    name: 'XingWei'
                    age: 23
                    sex: 中性-实例对象
                    >__proto__                  ```obj.__proto__ 实际上就是 obj对象的原型对象 Father.prototype ```
                        sex: '男-Father'
                        >constructor: f Father(name, age)
                        >__proto__              ```obj.__proto__.__proto__ 实际就是 Father.prototype.prototype ```
                            sex: '女-Object'
                            >constructor: f Object()
                            >valueOf: f valueOf()
                            >toString: f toString()
                            ... ... 
        */
    </script>
</body>

</html>

9. 扩展内置对象

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!--
        可以通过原型对象,对原来的内置对象进行扩展自定义的方法,比如给数组增加自定义求偶数和的功能; 
        ```定义在prototype原型对象上面的属性和方法, 可以被所有实例对象共享;```
      -->
    <script>
        console.log(Array.prototype);

        Array.prototype.sum = function () {
            var sum = 0;
            for (var i = 0; i < this.length; i++) {
                sum += this[i];
            }
            return sum;
        }
        var arr = [1, 2, 3];
        console.log(arr.sum());
        var Arr = new Array(11, 22, 33);
        console.log(Arr.sum());
    </script>
</body>

</html>

10. call方法的使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        call():
            1. 调用函数; 
            2. 修改函数运行时的this指向; 
     -->
</head>
<body>
    <script>
        function test() {
            console.log('test');
        }
        function fun(x, y) {
            console.log(this);
            console.log(x+y);
        }

        //1. call()可以调用函数
        test.call();

        //2. 改变this指向
        var obj = {
            name: 'andy'
        }
        fun(1, 4);                  // this指向window
        fun.call(obj, 1, 2);        // this指向obj了
    </script>
</body>
</html>

11. 构造函数的继承1

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- 
        ES6之前并没有给我们提供extends继承机制,
        但是我们可以通过 构造函数 + 原型对象 来模拟实现继承,称之为组合继承。 

        ES6, 2015.06发版。但是目前浏览器的JavaScript是ES5版本,大多数高版本的浏览器也支持ES6,
        但是只是实现了ES6的部分特性和功能。
        在ES6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征。
     -->
    <!-- 
         在子类的构造函数中调用父类的构造函数; (call())```
      -->
    <script>
        // 父构造函数
        function Father(_name, _age) {
            this.name = _name;
            this.age = _age;
            this.money = function () {
                console.log('100$');
            }
        }

        // 子构造函数
        function Son(_name, _age, _score) {
            Father.call(this, _name, _age); // 关键句 => 此时就可以调用父构造函数了
                                            // 通过call, 修改了Father构造函数中的this指向, 使其指向son,
                                            // 而后通过this.name, this.age, 也就相当于给Son添加了name, age, money属性了; 
                                            // 此时也就好比说实现了一种"继承", 子构造函数继承了父构造函数的系列属性
            this.score = _score;
        }

        var son = new Son('XingWei', 23, 100);
        console.log(son);

        /*
            console.log(son);
            >Son
                name: 'XingWei'
                age: 23
                money: f()
                score: 100
                >__proto__
                    constructor: f Son(_name, _age, _score)
                    __proto: ...
                        ... ...
        */
    </script>
</body>

</html>

12. 构造函数的继承2

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        两步:
            第1步: 在子类的构造函数中,调用父类的构造函数; 
            第2步: 让子类的原型指向父类的原型,这样子类就可以继承父类原型; (a 或 b都可以)
                   a. Son.prototype = new Father(); 
                      Son.prototype.constructor = Son; 

                   b. Son.prototype = Object.Create(Father.prototype);
                      Son.prototype.constructor = Son;
                
                   c.
                      以上两种写法都是可以的, 但是子类会具有父类实例的方法。有时,这可能不是我们需要的,所以不推荐使用这种写法; 
                      以上写法是子类是整体继承父类。有时只需要单个方法的继承,这时可以采用下面的写法; 
                        Son.prototype.money = function() {
                            Father.prototype.money.call(this); 
                        }
                      此种写法倒是更为简单易懂了, 就是在Son构造函数的原型之上添加了一个money方法, 然后就接下来就清晰了... ...; 
     -->
</head>

<body>
    <script>
        // 父构造函数
        function Father(_name, _age) {
            this.name = _name;
            this.age = _age;
            this.sing = function() {
                console.log('father-sing');
            }
        }
        Father.prototype.money = function () {
            console.log('10000000元RMB');
        }

        // 子构造函数
        function Son(_name, _age, _score) {
            Father.call(this, _name, _age);         
            this.score = _score;
        }
        Son.prototype.exam = function () {
            console.log('考试');
        }


        ///
        Son.prototype = new Father();           // son的原型对象指向father的实例对象, 此时就相当于继承了父亲的方法
        Son.prototype.constructor = Son;        // ***, 利用对象形式给原型对象赋值, 别忘了利用constructor指向原来的构造函数

        var son = new Son('ldh', 13, 199);
        son.sing();                             // 调用父类的方法
        son.money();                            // 调用父亲的方法
        console.dir(Son.prototype);
        console.dir(Father.prototype);
        console.log(son);

        // console.log(Son.prototype.constructor); // 指向的是构造函数Father,需更改指向,见***

        /*
        形式一: 
            Son.prototype = new Father(); 
            Son.prototype.constructor = Son;
                => 此时我们打印console.log(son);   
                >Son {name: "ldh", age: 13, score: 199}
                    name: 'ldh'
                    age: 13
                    sing: f()
                    score: 199
                    >__proto__
                        name: undefined
                        age: undefined
                        >constructor: f Son(_name, _age, _score)
                        >__proto__
                            >money: f()
                            constructor: f Father(_name, _age)
                            >__proto__
                                >constructor: f Object()
                                >toString: f toString()
                                >valueOf: f valueOf()
                                ...
                => 可以明显的看出:实例对象son的原型son.__proto__是实例对象 new Father();
                实例对象new Father()的__proto__是Father的原型Father.prototype;
                接下来就是Object了;                
        */

       /*
       形式二:
            Son.prototype = Object.create(Father.prototype);  // 返回的是一个基于Father.prototype创建的一个对象
            Son.prototype.constructor = Son;
                => 此时我们再次打印console.log(son);   
                >Son {name: "ldh", age: 13, score: 199}
                    name: 'ldh'
                    age: 13
                    sing: f()
                    score: 199
                    >__proto__          ```__proto__就是Object.create(Father.prototype)返回的这个对象, 该对象的constructor属性被指定为Son, 既然是对象, 那么肯定有__proto__属性了```
                        >constructor: f Son(_name, _age, _score)
                        >__proto__      ```返回的这个对象的原型是Father.prototype (son.__proto__.__proto__ === Father.prototype `true`)```
                            >money: f()
                            >constructor: f Father(_name, _age)
                            >__proto__
                                >constructor: f Object()
                                >toString: f toString()
                                >valueOf: f valueOf()
       */
    </script>


    <script>
        /*
            constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错; 
                function Person(_name, _age) {
                    this.name = _name;
                    this.age = _age;
                }
            1. 坏的写法:
                Person.prototype = {
                    method1: function() {  }
                    // ... 
                }; 
            2. 好的写法:
                Person.prototype = {
                    constructor: Person,
                    method1: function() {  }
                    // ...
                }; 
            3. 更好的写法:
                Person.prototype.method1 = function() {
                    ... 
                }
        */
    </script>
</body>

</html>

13. 构造函数的继承3

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        多重继承:
            JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能; 
            下面代码中,子类S同时继承了父类M1和M2。这种模式又称为 Mixin(混入)
     -->
</head>
<body>
    <script>
        // 父构造函数1
        function Man() {
            this.name1 = 'Zhang'; 
            this.play = function() {
                console.log('man like playing game!');
            }
        }
        Man.prototype.run = function() {
            console.log('man like running!');
        }
        // 父构造函数2
        function Woman() {
            this.name2 = 'Wang'; 
            this.sing = function () { 
                console.log('woman like singing a song!');
             }
        }
        Woman.prototype.dance = function() {
            console.log('woman like dancing!');
        }

        // 子类
        function Son() {
            Man.call(this); 
            Woman.call(this);
        }
        // 继承Man
        Son.prototype = Object.create(Man.prototype); 
        // 继承链上再加入Woman
        Object.assign(Son.prototype, Woman.prototype); // 也即是将Woman.prototype对象的属性给拷贝到Son.prototype对象上
                                                       /* 
                                                            Man.prototype:
                                                                >{run: ƒ, constructor: ƒ}
                                                                    run: f()
                                                                    constructor: f Man()
                                                                    __proto__: 
                                                                        ... ... 

                                                            Object.assign(Man.prototype, Woman.prototype) 回车键
                                                            >{ fun: f, dance: f, constructor: f }
                                                                >run: f()
                                                                >dance: f()
                                                                >constructor: f Man()
                                                                >__proto__: 
                                                                        ... ...
                                                            在控制台中直接调试打印即可; 
                                                       */
        //
        Son.prototype.constructor = Son;


        var son = new Son();
        son.play();
        son.sing();
        son.run();
        son.dance();
        console.log(son);

        /*
            console.log(son); 
            >Son {name1: "Zhang", name2: "Wang", play: ƒ, sing: ƒ}
                name1: 'Zhang'
                play: f()
                name2: 'Wang'
                sing: f()
                >__proto__              ```son.__proto__是Son.prototype, 是Object.create(Man.prototype)返回的一个对象, 该对象上有dance(),constructor(),__proto__```
                    >dance: f()
                    >constructor: f Son()
                    >__proto__          ```son.__proto__.__proto__ === Man.prototype  `true`   ```
                        >run: f()
                        >constructor: f Man()
                        >__proto__
                            >constructor: f Object()
                            >toString: f toString()
                            >valueOf: f valueOf()
                            >isPrototypeOf: f isPrototypeOf()
                                ...     ...
        */
    </script>
</body>
</html>

14. this指向

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 
        总结一下,JavaScript语言之中,一切皆对象,运行环境也是对象; 
        所以函数都是在某个对象之中运行,this就是函数运行时所在的对象(环境); 
        这本来并不会让用户糊涂,但是JavaScript支持运行环境动态切换; 
        也就是说,this的指向是动态的,没有办法事先确定到底指向哪个对象,这才是最让人感到困惑的地方; 
     -->
    <!-- 
         使用场合:
            1.全局环境:    全局环境使用this,它指的就是顶层对象window; 
            2.构造函数:    构造函数中的this,指的是实例对象; 
            3.对象的方法:  如果对象的方法里面包含this,this的指向就是方法运行时所在的对象; 该方法赋值给另一个对象,就会改变this的指向; 
      -->
</head>

<body>
    <script>
        /*
            1. 下面代码说明,不管是不是在函数内部,只要是在全局环境下运行,this就是指顶层对象window; 
        */
        console.log(this === window);       // true
        function fun() {
            console.log(this === window);   // true
        }
        fun();
        console.log('----------');
    </script>

    <script>
        /*
            2. 如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层; 
                (1) a.age.m方法在对象a的第二层,该方法内部的this不是指向对象a, 而是指向对象a.age, 而a.age并没有name属性, 那么自然是undefined了;
        */
        var a = {
            name: 'Hello',
            age: {
                m: function () {
                    console.log(this.name); 
                }
            }
        };
        a.age.m();  // undefined
        console.log('----------');
    </script>

    <script>
        /*
            3. 避免多层 this: 由于this的指向是不确定的,所以切勿在函数中包含多层的this; 
        */
        var ooo = {
            name: 'Zhang',
            f1: function () {
                console.log(this);          // this指向对象ooo
                var f2 = function () {
                    console.log(this);      // this指向顶层对象window
                }();                        // 注意,此处的f2指向的函数自动被调用了(多了一个"()")
            }   
        };
        ooo.f1();
        /* 
            (1) 因此实际执行的是以下的代码: 
                var temp = function() {
                    console.log(this);
                };
                var ooo = {
                    f1: function() {
                        console.log(this);
                        var f2 = temp();
                    }
                }  
        */
        /*
            (2) 一个解决方法是在第二层改用一个指向外层this的变量; 
                事实上,使用一个变量固定this的值,然后内层函数调用这个变量,是非常常见的做法,请务必掌握; 
        */ 
        var oooo = {
            name: 'Zhang',
            f1: function () {
                console.log(this);
                var that = this;
                var f2 = function () {
                    console.log(that);
                }();
            }
        };
        oooo.f1();


        /*
            (3) JavaScript 提供了严格模式,也可以硬性避免这种问题。严格模式下,如果函数内部的this指向顶层对象Window,就会报错; 
        */
        var counter = { count: 0 };
          counter.inc = function () {
              'use strict';
              this.count++;
          };
          var ff = counter.inc;
          ff();           // Uncaught TypeError: Cannot read property 'count' of undefined
    </script>


    <!-- test -->
    <script>
        var f = function () {
            console.log('hello world');
        }();    // 将立即调用该函数
    </script>
</body>

</html>

15. Object对象的相关方法1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        /* 
            1. Object.getPrototypeOf(): 返回参数对象的原型; 
            2. 特殊对象的原型:
                (1) 空对象的原型是 Object.prototype; 
                    Object.getPrototypeOf({}) === Object.prototype      //true
                (2) Object.prototype 的原型是 null; 
                    Object.getPrototypeOf(Object.prototype) === null    //true
                (3) 函数的原型是 Function.prototype; 
                    Object.getPrototypeOf(function f() {}) === Function.prototype   // true
        */
    </script>


    <script>
        /*
            3. Object.setPrototypeOf(): 为参数对象设置原型,返回该参数对象; 
                (1) 它接受两个参数,第一个是现有对象,第二个是原型对象;
                (2) 下面代码中,Object.setPrototypeOf方法将对象a的原型设置为对象b,因此a可以共享b的属性; 
        */
        var a = {};
        var b = {num: 101};
        Object.setPrototypeOf(a, b);            // 对象a的原型为对象b
        Object.getPrototypeOf(a) === b;         // true
        console.log(a.num);
        console.log('----------');
    </script>


    <script>
        /*
            4. Object.create(): 该方法接受一个对象作为参数,然后以它为原型,返回一个实例对象。该实例对象完全继承原型对象的属性; 
                (1) 上面代码中,Object.create方法以A对象为原型,生成了B对象。B继承了A的所有属性和方法; 
        */
        // 原型对象
        var A = {
            print: function() {
                console.log('hello');
            }
        };
        // 实例对象
        var B = Object.create(A);
        console.log(Object.getPrototypeOf(B) === A);    // true
        B.print();
        console.log(B.print === A.print);               // true
        console.log('----------');
    </script>

    <script>
        /* 
            5.
                (1) 如果想要生成一个不继承任何属性(比如没有toString和valueOf方法)的对象,可以将Object.create的参数设为null;   
                            var Obj4 = Object.create(null);
                            console.log(Obj4);
                (2) 使用Object.create方法的时候,必须提供对象原型,参数为空或参数不是对象时,会报错; 
                            Object.create();     // ERROR
                            Object.create(123);  // ERROR
                (3) Object.create方法生成的新对象,动态继承了原型。在原型上添加或修改任何方法,会立刻反映在新对象之上; 
                            var obj1 = {
                                name: 'Zhang'
                            };
                            var obj2 = Object.create(obj1);
                            obj1.sing = 'LaDing';
                            console.log(obj2);
        */
        // 以下三种写法是等价的
        var Obj1 = Object.create({});
        var Obj2 = Object.create(Object.prototype);
        var Obj3 = new Object();
        console.log(Obj1);
        console.log(Obj2);
        console.log(Obj3);
        console.log('----------');
    </script>

    <script>
        /*
            6. 除了对象的原型,Object.create方法还可以接受第二个参数; 
               该参数是一个属性描述对象,它所描述的对象属性,会添加到实例对象,作为该对象自身的属性; 
        */
        var Object = Object.create({}, {
            name: {
                value: 'Wang',
                enumerable: true,
                configurable: true,
                writable: true
            },
            age: {
                value: 88,
                enumerable: true,
                configurable: true,
                writable: true
            }
        });
        //以上等价于:
        /* var Object = Object.create({});
        Object.name = "Wang";
        Object.age = 88; */
        console.log(Object);
    </script>

     <script>
         /* 
            7. Object.prototype.isPrototypeOf(): 用来判断该对象是否为参数对象的原型; 
                    var o1 = {};
                    var o2 = Object.create(o1);
                    var o3 = Object.create(o2);

                    o1.isPrototypeOf(o3)        // true
                    o2.isPrototypeOf(o3)        // true

                    Object.prototype.isPrototypeOf({})                      // true
                    Object.prototype.isPrototypeOf([])                      // true
                    Object.prototype.isPrototypeOf(/xyz/)                   // true
                    Object.prototype.isPrototypeOf(Object.create(null))     // false
                   上面代码中,由于Object.prototype处于原型链的最顶端,所以对各种实例都返回true,只有直接继承自null的对象除外; 
         */
     </script>
</body>
</html>

16. Object对象的相关方法2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        /*
            1. Object.prototype.__proto__:
                (1) 实例对象的__proto__属性(前后各两个下划线),返回该对象的原型。该属性可读写; 
                (2) 根据语言标准,__proto__属性只有浏览器才需要部署,其他环境可以没有这个属性;
                    它前后的两根下划线,表明它本质是一个内部属性,不应该对使用者暴露; 
                    因此,应该尽量少用这个属性,而是用Object.getPrototypeof()和Object.setPrototypeOf(),进行原型对象的读写操作;
                            var obj = {};
                            var p = {};
                            obj.__proto__ = p;
                            Object.getPrototypeOf(obj) === p;       // true
                    上面代码通过__proto__属性,将p对象设为obj对象的原型; 
        */
        var A = {
            name: 'Zhang'
        };
        var B = {
            name: 'Wang'
        };
        var proto = {
            show: function() {
                console.log(this.name);
            }
        };
        A.__proto__ = proto;
        B.__proto__ = proto;
        A.show();
        B.show();
        console.log(A.show === B.show);         // true
        console.log(A.show === proto.show);     // true
        console.log(B.show === proto.show);     // true
        // 上面代码中,A对象和B对象的原型都是proto对象,它们都共享proto对象的print方法。
        // 也就是说,A和B的print方法,都是在调用proto对象的print方法。
        console.log('----------');
    </script>

    <script>
        /*
            3. 获取原型对象方法的比较:
                (1) 如前所述,__proto__属性指向当前对象的原型对象,即构造函数的prototype属性; 
                        var obj = new Object();
                        obj.__proto__ === Object.prototype;                 // true
                        obj.__proto__ === Object.constructor.prototype;     // true
                (2) 因此,获取实例对象obj的原型对象,有三种方法:
                    a. obj.__proto__; 
                    b. obj.constructor.prototype; 
                    c. Object.getPrototypeOf(obj); 
        */
    </script>


    <script>
        /*
            4. Object.getOwnPropertyNames(): 返回一个数组,成员是参数对象本身的所有属性的键名(不管是否可以遍历),不包含继承的属性键名; 
            5. Object.prototype.hasOwnProperty():返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上; 
        */
        console.log(Object.getOwnPropertyNames(Date));
        console.log(Date.hasOwnProperty('length'));     // true, Date.length是Date自身的属性
        console.log(Date.hasOwnProperty('toString'));   // false, Date.toString是继承的属性
    </script>


    <script>
        /*
            6. in 运算符和 for…in 循环:
                (1) in运算符返回一个布尔值,表示一个对象是否具有某个属性; 它不区分该属性是对象自身的属性,还是继承的属性; 
                        console.log('length' in Date);      // true
                        console.log('toString' in Date);    // true
                (2) 获得对象的所有可遍历属性(不管是自身的还是继承的),可以使用for...in循环; 
                        下面代码中,对象oo2的age属性是自身的,name属性是继承的。这两个属性都会被for...in循环遍历; 
                        为了在for...in循环中获得对象自身的属性,可以采用hasOwnProperty方法判断一下; 
                            for(var name in object) {
                                if(object.hasOwnProperty(name)) {
                                    // ... ... 
                                }
                            }

        */
        var oo1 = {
            name: 'Zhang'
        };
        var oo2 = Object.create(oo1, {
            age: {
                value: 23,
                enumerable: true,
                configurable: true,
                writable: true
            }
        });
        for(key in oo2) {
            console.log(key);
        }   // age, name
        console.log('----------');
    </script>


    <script>
        function Father(name, age) {
            this.name = name;
            this.age = age;
        };
        Father.prototype.show = function() {
            console.log('Hello');
        }
        function Son() {
        }
        Son.prototype = new Father('zhang',101);
        // console.dir(Father);
        console.dir(Son);
    </script>
</body>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/574340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PLX31-EIP-MBS 以太网/IP到Modbus串行

PLX31-EIP-MBS ProSoft Technology的EtherNet/IP to Modbus串行通信网关允许在EtherNet/IP PACs或设备与支持Modbus的PACs或设备之间进行高速双向数据传输。 EtherNet/IP PACs包括Rockwell Automation ControlLogix和CompactLogix&#xff0c;以及几款施耐德电气控制器。Mod…

NameServer总结

NameServer是一个注册中心&#xff0c;提供服务注册和服务发现的功能。NameServer可以集群部署&#xff0c;集群中每个节点都是对等的关系&#xff08;没有像ZooKeeper那样在集群中选举出一个Master节点&#xff09;&#xff0c;节点之间互不通信。服务注册 Broker启动的时候会…

Eclipse教程Ⅲ

Eclipse 菜单 Eclipse 查看的菜单栏通常包含以下几个菜单&#xff1a; File 菜单Edit 菜单Navigate 菜单Search 菜单Project 菜单Run 菜单Window 菜单Help 菜单 通过 Eclipse 插件你可以添加新的菜单和菜单项。 菜单描述 菜单名描述FileFile 菜单运行你打开文件&#xff0c;…

同余方程 乘法逆元 扩展欧几里得算法 5.26

同余方程 乘法逆元 扩展欧几里得算法 526 同余方程 乘法逆元 扩展欧几里得算法_哔哩哔哩_bilibili 给定整数a,b,m&#xff0c;求解同余方程axb(mod m). 如果x存在整数解&#xff0c;则输出任意一个&#xff1b; 如果不存在&#xff0c;则输出none 例&#xff1a; 8x4(mod…

动态线程池 dynamic-tp 源码

目录 1. 介绍 2. Spring 环境整合配置源码 2.1 DtpBeanDefinitionRegistrar 2.2 DtpPostProcessorRegistrar 2.3 ApplicationContextHolder 2.4 DtpBaseBeanConfiguration 2. 动态线程池 DtpLifecycle 生命周期源码 3. 动态线程池 DtpRegistry 注册源码 4. 动态线程池…

基于51单片机的两路数字电压表Protues仿真设计

目录 一、设计背景 1.1、数字电压表的发展历程 1.2、课题的意义和目的 二、实现功能 三、仿真演示 四、部分程序展示 一、设计背景 1.1、数字电压表的发展历程 数字电压表简称DVM&#xff0c;它是采用数字化测量技术设计的电压表。从性能来看&#xff1a;数字电压表的发展从…

MYSQL索引连环18问(上)

MYSQL索引连环18问&#xff08;上&#xff09; 1.索引是什么&#xff1f; 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)&#xff0c;它们包含着对数据表里所有记录的引用指针。索引是一种数据结构。数据库索引&#xff0c;是数据库管理系统中一个排序的…

PLX31-EIP-SIE 以太网/IP到西门子工业以太网

ProSoft Technology的EtherNet/IP to Siemens工业以太网通信网关允许支持EtherNet/IP的控制器或设备与西门子S7 PACs(包括S7-200s、S7-300s、S7-400s、S7-1200和S7-1500 PACs)之间进行高速双向数据传输。 此外&#xff0c;该网关还包括几个功能&#xff0c;包括数据优先级&…

我在GPT小程序开发中踩过的5个坑

坑1&#xff1a;没有充分了解需求 在GPT小程序开发中&#xff0c;充分了解需求十分重要。如果你没有认真地与客户交流&#xff0c;并理解他们的需求和期望&#xff0c;那么你很可能会浪费很多时间在错误的方向上。 坑2&#xff1a;没有使用合适的开发工具 在GPT小程序开发中…

Shell脚本攻略:Shell编程规范与变量

一、理论 1.Shell脚本编程规范 &#xff08;1&#xff09;Shell简介 Linux 系统中的 Shell 是一个特殊的应用程序&#xff0c;它介于操作系统内核与用户之间&#xff0c;充当 了一个“命令解释器”的角色&#xff0c;负责接收用户输入的操作指令&#xff08;命令&#xff09…

从小白到大神之路之学习运维第28天

第二阶段基础 时 间&#xff1a;2023年5月24日 参加人&#xff1a;全班人员 内 容&#xff1a; ISCSI服务 目录 实验构建iscsi服务 实现步骤&#xff1a;以下实验为例 前提配置&#xff1a; 服务器端&#xff1a; 客户端&#xff1a; 注意事项&#xff1a; 实验构…

新手一定要掌握的实用调试技巧(vs2019)

目录 1、什么是bug&#xff1f; 2、调试是什么&#xff1f; 2.1、调试是什么 2.2、调试的基本步骤 2.3、Debug和Release的介绍 3、Windows环境调试介绍 3.1、调试环境的准备 3.2、学会快捷键 3.3、调试的时候查看程序当前信息 3.3.1、查看临时变量的值 3.3.2、查看内存信息…

【PWN · IntegerOverflow ret2text】[BJDCTF 2020]babystack2.0

第一次遇见整数溢出的题目&#xff0c;值得记录一下&#xff08;虽然这里的整数溢出很简单 目录 前言 一、整数溢出 二、解题思路 1.ELF/checksec查看保护 2.IDA反汇编 3.整数溢出 4.exp编写 总结 前言 整数溢出漏洞——对于有/无符号数&#xff0c;长/短位宽转换时机…

什么是 Spring Boot Actuator?如何在 Spring Boot 中使用 Actuator?

当我们在开发和部署应用程序时&#xff0c;监控应用程序的健康状况和性能是非常重要的。Spring Boot Actuator 为我们提供了一组现成的端点&#xff08;endpoints&#xff09;&#xff0c;可以让我们方便地监控和管理应用程序。在本文中&#xff0c;我们将了解 Spring Boot Act…

Spark+Kafka构建实时分析Dashboard

SparkKafka构建实时分析Dashboard 说明一、案例介绍二、实验环境准备1、实验系统和软件要求2、系统和软件的安装&#xff08;1&#xff09;安装Spark&#xff08;2&#xff09;安装Kafka&#xff08;3&#xff09;安装Python&#xff08;4&#xff09;安装Python依赖库&#xf…

数据仓库hive本地/远程模式安装

文章目录 1.简述2.本地模式2.1安装包准备2.2解压安装mysql2.2.1 解压mysql安装包2.2.2 安装mysql相关组件2.2.3 修改my.cnf配置文件2.2.4 更改所属组2.2.5 启动mysql服务 2.3 hive解压安装及配置2.3.1 解压2.3.2 改名2.3.3 配置环境变量2.3.4 添加hive-site.xml配置文件2.3.5 放…

《Spring Guides系列学习》guide6 - guide10

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 接着上篇看过的gu…

VIBRO METER 带缓冲输出的机械监控系统接口套件

高质量、高可靠性的接口套件&#xff0c;用于现有机械监控系统的缓冲“原始”传感器输出信号。该接口套件支持多达25个通道&#xff0c;可以是动态或转速计(速度)信号。接口套件采用DIN导轨安装&#xff0c;通常安装在装有VM600或VibroSmart机械监控系统的外壳中。 特征 支持…

为 Kotlin 的函数添加作用域限制(以 Compose 为例)

前言 不知道各位是否已经开始了解 Jetpack Compose&#xff1f; 如果已经开始了解并且上手写过。那么&#xff0c;不知道你们有没有发现&#xff0c;在 Compose 中对于作用域&#xff08;Scopes&#xff09;的应用特别多。比如&#xff0c; weight 修饰符只能用在 RowScope 或…

docker快速部署hue+hue集成hive

首先需要安装hive&#xff0c;hive的安装在HIVE的安装与配置_EEEurekaaa&#xff01;的博客-CSDN博客 安装完成之后&#xff0c;使用脚本命令启动hdfs和hive的相关服务。 一、安装docker # 安装yum-config-manager配置工具 $ yum -y install yum-utils # 设置yum源 $ yum-co…