中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript面向對象的思維特點是什么

發布時間:2022-01-30 19:00:35 來源:億速云 閱讀:149 作者:iii 欄目:web開發

這篇“JavaScript面向對象的思維特點是什么”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“JavaScript面向對象的思維特點是什么”文章吧。

JavaScript面向對象的思維特點是什么

1、面向對象

面向對象更貼近我們的實際生活, 可以使用面向對象描述現實世界事物. 但是事物分為具體的事物和抽象的事物

面向對象的思維特點:

  1. 抽取(抽象)對象共用的屬性和行為組織(封裝)成一個類(模板)

  2. 對類進行實例化, 獲取類的對象

1.1、對象

在 JavaScript 中,對象是一組無序的相關屬性和方法的集合,所有的事物都是對象,例如字符串、數值、數組、函數等。

對象是由屬性方法組成的

  • 屬性:事物的特征,在對象中用屬性來表示

  • 方法:事物的行為,在對象中用方法來表示

1.2、類

在 ES6 中新增加了類的概念,可以使用 class 關鍵字聲明一個類,之后以這個類來實例化對象。

  • 抽象了對象的公共部分,它泛指某一大類(class)

  • 對象特指某一個,通過類實例化一個具體的對象

1.2.1、創建類

class name {
    // class body}
  • 創建實例

var XX = new name();

注意:類必須使用new 實例化對象

1.2.2、構造函數

constructor()方法是類的構造函數(默認方法),用于傳遞參數,返回實例對象,通過 new 命令生成對象實例時,自動調用該方法。如果沒有顯示定義, 類內部會自動給我們創建一個constructor()

<script>
    // 1. 創建類 class  創建一個 明星類
    class Star {
        // constructor 構造器或者構造函數
        constructor(uname, age) {
            this.uname = uname;
            this.age = age;
        }
    }

    // 2. 利用類創建對象 new
    var ldh = new Star('劉德華', 18);
    var zxy = new Star('張學友', 20);
    console.log(ldh);
    console.log(zxy);</script>
  • 通過 class 關鍵字創建類,類名我們還是習慣性定義首字母大寫

  • 類里面有個 constructor函數,可以接收傳遞過來的參數,同時返回實例對象

  • constructor函數只要 new 生成實例時,就會自動調用這個函數,如果我們不寫這個函數,類也會自動生成這個函數

  • 最后注意語法規范

    • 創建類?類名后面不要加小括號

    • 生成實例?類名后面加小括號

    • 構造函數不需要加 function 關鍵字

1.2.3、類中添加方法

語法:

class Person {
  constructor(name,age) {   
      // constructor 稱為構造器或者構造函數
      this.name = name;
      this.age = age;
    }
   say() {
      console.log(this.name + '你好');
   }}      var ldh = new Person('劉德華', 18); ldh.say()

注意: 方法之間不能加逗號分隔,同時方法不需要添加 function 關鍵字。

<script>
    // 1. 創建類 class  創建一個 明星類
    class Star {
        // 類的共有屬性放到 constructor 里面
        constructor(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        sing(song) {
            console.log(this.uname + song);
        }
    }

    // 2. 利用類創建對象 new
    var ldh = new Star('劉德華', 18);
    var zxy = new Star('張學友', 20);
    console.log(ldh);
    console.log(zxy);
    // (1) 我們類里面所有的函數不需要寫function 
    // (2) 多個函數方法之間不需要添加逗號分隔
    ldh.sing('冰雨');
    zxy.sing('李香蘭');</script>
  • 類的共有屬性放到constructor 里面

  • 類里面的函數都不需要寫 function 關鍵字

1.3 、類的繼承

現實中的繼承:子承父業,比如我們都繼承了父親的姓。

程序中的繼承:子類可以繼承父類的一些屬性和方法。

語法:

// 父類class Father {
    }// 子類繼承父類class Son extends Father {
    }

看一個實例:

<script>
    // 父類有加法方法
    class Father {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        sum() {
            console.log(this.x + this.y);
        }
    }
    // 子類繼承父類加法方法 同時 擴展減法方法
    class Son extends Father {
        constructor(x, y) {
            // 利用super 調用父類的構造函數
            // super 必須在子類this之前調用
            super(x, y);
            this.x = x;
            this.y = y;
        }
        subtract() {
            console.log(this.x - this.y);
        }
    }
    var son = new Son(5, 3);
    son.subtract();
    son.sum();</script>

1.4、super關鍵字

  • super 關鍵字用于訪問和調用對象父類上的函數,可以調用父類的構造函數,也可以調用父類的普通函數

1.4.1、調用父類的構造函數

語法:

// 父類class Person {
    constructor(surname){
        this.surname = surname;
    }}// 子類繼承父類class Student entends Person {
    constructor(surname,firstname) {
        super(surname);					//調用父類的 constructor(surname)
        this.firstname = firstname;		//定義子類獨有的屬性
    }}

注意:子類在構造函數中使用super,必須放到this前面(必須先調用父類的構造方法,在使用子類構造方法)

案例:

// 父類class Father {
    constructor(surname){
        this.surname = surname;
    }
    saySurname() {
        console.log('我的姓是' + this.surname);
    }}// 子類繼承父類class Son entends Father {
    constructor(surname,firstname) {
        super(surname);					//調用父類的 constructor(surname)
        this.firstname = firstname;		//定義子類獨有的屬性
    }
    sayFirstname() {
        console.log('我的名字是:' + this.firstname);
    }}var damao = new Son('劉','德華');damao.saySurname();damao.sayFirstname();

1.4.2、調用父類的普通函數

語法:

class Father {
    say() {
        return '我是爸爸';
    }}class Son extends Father {
    say(){
        // super.say() super調用父類的方法
        return super.say() + '的兒子';
    }}var damao = new Son();console.log(damao.say());
  • 多個方法之間不需要添加逗號分隔

  • 繼承中屬性和方法的查找原則:就近原則,先看子類,再看父類

1.4、三個注意點

  1. 在ES6中類沒有變量提升,所以必須先定義類,才能通過類實例化對象

  2. 類里面的共有屬性和方法一定要加 this使用

  3. 類里面的this指向:

    • constructor 里面的 this指向實例對象

    • 方法里面的this指向這個方法的調用者

<body>
    <button>點擊</button>
    <script>
        var that;
        var _that;
        class Star {
            constructor(uname, age) {
                // constructor 里面的this 指向的是 創建的實例對象
                that = this;
                this.uname = uname;
                this.age = age;
                // this.sing();
                this.btn = document.querySelector('button');
                this.btn.onclick = this.sing;
            }
            sing() {
            // 這個sing方法里面的this 指向的是 btn 這個按鈕,因為這個按鈕調用了這個函數
                console.log(that.uname); 
                // that里面存儲的是constructor里面的this
            }
            dance() {
                // 這個dance里面的this 指向的是實例對象 ldh 因為ldh 調用了這個函數
                _that = this;
                console.log(this);
            }
        }
        var ldh = new Star('劉德華');
        console.log(that === ldh);
        ldh.dance();
        console.log(_that === ldh);

        // 1. 在 ES6 中類沒有變量提升,所以必須先定義類,才能通過類實例化對象

        // 2. 類里面的共有的屬性和方法一定要加this使用.
    </script></body>

2、構造函數和原型

2.1、概述

在典型的 OOP 的語言中(如 Java),都存在類的概念,類就是對象的模板,對象就是類的實例,但在 ES6之前, JS 中并沒用引入類的概念。

ES6, 全稱 ECMAScript 6.0 ,2015.06 發版。但是目前瀏覽器的 JavaScript 是 ES5 版本,大多數高版本的瀏覽器也支持 ES6,不過只實現了 ES6 的部分特性和功能。

在 ES6之前 ,對象不是基于類創建的,而是用一種稱為構建函數的特殊函數來定義對象和它們的特征。

  • 創建對象有三種方式

    • 對象字面量

    • new Object()

    • 自定義構造函數

// 1. 利用 new Object() 創建對象var obj1 = new Object();// 2. 利用對象字面量創建對象var obj2 = {};// 3.利用構造函數創建對象function Star(uname,age) {
    this.uname = uname;
    this.age = age;
    this.sing = function() {
        console.log('我會唱歌');
    }}var ldh = new Star('劉德華',18);

注意:

  1. 構造函數用于創建某一類對象,其首字母要大寫

  2. 構造函數要和new一起使用才有意義

2.2、構造函數

  • 構造函數是一種特殊的函數,主要用來初始化對象(為對象成員變量賦初始值),它總與new一起使用

  • 我們可以把對象中的一些公共的屬性和方法抽取出來,然后封裝到這個函數里面

new 在執行時會做四件事

  1. 在內存中創建一個新的空對象。

  2. 讓 this 指向這個新的對象。

  3. 執行構造函數里面的代碼,給這個新對象添加屬性和方法。

  4. 返回這個新對象(所以構造函數里面不需要 return )。

2.2.1、靜態成員和實例成員

JavaScript 的構造函數中可以添加一些成員,可以在構造函數本身上添加,也可以在構造函數內部的this上添加。通過這兩種方式添加的成員,就分別稱為靜態成員實例成員

  • 靜態成員:在構造函數本身上添加的成員為靜態成員,只能由構造函數本身來訪問

  • 實例成員:在構造函數內部創建的對象成員稱為實例成員,只能由實例化的對象來訪問

// 構造函數中的屬性和方法我們稱為成員,成員可以添加
function Star(uname,age) {
    this.uname = uname;
    this.age = age;
    this.sing = function() {
        console.log('我會唱歌');
    }
}
var ldh = new Star('劉德華',18);

// 實例成員就是構造函數內部通過this添加的成員  uname age sing  就是實例成員
// 實例成員只能通過實例化的對象來訪問
ldh.sing();
Star.uname; // undefined     不可以通過構造函數來訪問實例成員

// 靜態成員就是在構造函數本身上添加的成員 sex 就是靜態成員
// 靜態成員只能通過構造函數來訪問
Star.sex = '男';
Star.sex;
ldh.sex; // undefined  不能通過對象來訪問

2.2.2、構造函數的問題

構造函數方法很好用,但是存在浪費內存的問題

JavaScript面向對象的思維特點是什么

  • 我們希望所有的對象使用同一個函數,這樣就比較節省內存

2.3、構造函數原型 prototype

  • 構造函數通過原型分配的函數是所有對象所共享的,這樣就解決了內存浪費問題

  • JavaScript 規定,每一個構造函數都有一個prototype屬性,指向另一個對象,注意這個prototype就是一個對象,這個對象的所有屬性和方法,都會被構造函數所擁有

  • 我們可以把那些不變的方法,直接定義在prototype 對象上,這樣所有對象的實例就可以共享這些方法

<body>
    <script>
        // 1. 構造函數的問題. 
        function Star(uname, age) {
    		//公共屬性定義到構造函數里面
            this.uname = uname;
            this.age = age;
            // this.sing = function() {
            //     console.log('我會唱歌');
            // }
        }
		//公共的方法我們放到原型對象身上
        Star.prototype.sing = function() {
            console.log('我會唱歌');
        }
        var ldh = new Star('劉德華', 18);
        var zxy = new Star('張學友', 19);
        console.log(ldh.sing === zxy.sing);
        ldh.sing();
        zxy.sing();
        // 2. 一般情況下,我們的公共屬性定義到構造函數里面, 公共的方法我們放到原型對象身上
    </script></body>
  • 一般情況下,我們的公共屬性定義到構造函數里面, 公共的方法我們放到原型對象身上

問答:原型是什么?

  • 一個對象,我們也稱為 prototype原型對象

問答:原型的作用是什么?

  • 共享方法

2.4、對象原型 __ proto __

  • 對象都會有一個屬性 _proto_ 指向構造函數的prototype原型對象,之所以我們對象可以使用構造函數prototype 原型對象的屬性和方法,就是因為對象有_proto_原型的存在。

  • _proto_對象原型和原型對象 prototype 是等價的

  • _proto_對象原型的意義就在于為對象的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型對象 prototype

JavaScript面向對象的思維特點是什么

  • Star.prototype 和 ldh._proto_ 指向相同

<body>
    <script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Star.prototype.sing = function() {
            console.log('我會唱歌');
        }
        var ldh = new Star('劉德華', 18);
        var zxy = new Star('張學友', 19);
        ldh.sing();
        console.log(ldh); 
		// 對象身上系統自己添加一個 __proto__ 指向我們構造函數的原型對象 prototype
        console.log(ldh.__proto__ === Star.prototype);
        // 方法的查找規則: 首先先看ldh 對象身上是否有 sing 方法,如果有就執行這個對象上的sing
        // 如果沒有sing 這個方法,因為有 __proto__ 的存在,就去構造函數原型對象prototype身上去查找sing這個方法
    </script></body>

2.5、constructor 構造函數

  • 對象原型(__ proto __)構造函數(prototype)原型對象里面都有一個屬性constructor屬性, constructor 我們稱為構造函數,因為它指回構造函數本身。

  • constructor主要用于記錄該對象引用于哪個構造函數,它可以讓原型對象重新指向原來的構造函數

  • 一般情況下,對象的方法都在構造函數(prototype)的原型對象中設置

  • 如果有多個對象的方法,我們可以給原型對象prototype采取對象形式賦值,但是這樣會覆蓋構造函數原型對象原來的內容,這樣修改后的原型對象constructor就不再指向當前構造函數了。此時,我們可以在修改后的原型對象中,添加一個constructor指向原來的構造函數

具體請看實例配合理解

<body>
    <script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        // 很多情況下,我們需要手動的利用constructor 這個屬性指回 原來的構造函數
        // Star.prototype.sing = function() {
        //     console.log('我會唱歌');
        // };
        // Star.prototype.movie = function() {
        //     console.log('我會演電影');
        // }
        Star.prototype = {
            // 如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用constructor指回原來的構造函數
            constructor: Star,
            sing: function() {
                console.log('我會唱歌');
            },
            movie: function() {
                console.log('我會演電影');
            }
        }
        var ldh = new Star('劉德華', 18);
        var zxy = new Star('張學友', 19);
    </script></body>

2.6、構造函數、實例、原型對象三者關系

JavaScript面向對象的思維特點是什么

2.7、原型鏈查找規則

  1. 當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性

  2. 如果沒有就查找它的原型(也就是_proto_指向的prototype原型對象)

  3. 如果還沒有就查找原型對象的原型(Object的原型對象)

  4. 依次類推一直找到Object為止(null)

  5. __ proto __對象原型的意義就在于為對象成員查找機制提供一個方向,或者說一條路線。

JavaScript面向對象的思維特點是什么

<body>
    <script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        Star.prototype.sing = function() {
            console.log('我會唱歌');
        }
        var ldh = new Star('劉德華', 18);
        // 1. 只要是對象就有__proto__ 原型, 指向原型對象
        console.log(Star.prototype);
        console.log(Star.prototype.__proto__ === Object.prototype);
        // 2.我們Star原型對象里面的__proto__原型指向的是 Object.prototype
        console.log(Object.prototype.__proto__);
        // 3. 我們Object.prototype原型對象里面的__proto__原型  指向為 null
    </script></body>

2.8、原型對象this指向

  • 構造函數中的 this指向我們的實例對象

  • 原型對象里面放的是方法,這個方法里面的this指向的是這個方法的調用者,也就是這個實例對象

<body>
    <script>
        function Star(uname, age) {
            this.uname = uname;
            this.age = age;
        }
        var that;
        Star.prototype.sing = function() {
            console.log('我會唱歌');
            that = this;
        }
        var ldh = new Star('劉德華', 18);
        // 1. 在構造函數中,里面this指向的是對象實例 ldh
        ldh.sing();
        console.log(that === ldh);

        // 2.原型對象函數里面的this 指向的是 實例對象 ldh
    </script></body>

2.9、擴展內置對象

  • 可以通過原型對象,對原來的內置對象進行擴展自定義的方法

  • 比如給數組增加自定義求偶數和的功能

<body>
    <script>
        // 原型對象的應用 擴展內置對象方法

        Array.prototype.sum = function() {
            var sum = 0;
            for (var i = 0; i < this.length; i++) {
                sum += this[i];
            }
            return sum;
        };
        // 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());
        console.log(Array.prototype);
        var arr1 = new Array(11, 22, 33);
        console.log(arr1.sum());
    </script></body>

注意:

  • 數組和字符串內置對象不能給原型對象覆蓋操作Array.prototype = {},只能是Array.prototype.xxx = function(){}的方式

3、繼承

ES6 之前并沒有給我們提供extends繼承

  • 我們可以通過構造函數+原型對象模擬實現繼承,被稱為組合繼承

3.1、call()

調用這個函數,并且修改函數運行時的 this 指向

fun.call(thisArg,arg1,arg2,......)
  • thisArg:當前調用函數 this 的指向對象

  • arg1,arg2: 傳遞的其他參數

示例

<body>
    <script>
        // call 方法
        function fn(x, y) {
            console.log('我希望我的希望有希望');
            console.log(this);		// Object{...}
            console.log(x + y);		// 3
        }

        var o = {
            name: 'andy'
        };
        // fn();
        // 1. call() 可以調用函數
        // fn.call();
        // 2. call() 可以改變這個函數的this指向 此時這個函數的this 就指向了o這個對象
        fn.call(o, 1, 2);
    </script></body>

3.2、借用構造函數繼承父類型屬性

  • 核心原理: 通過 call() 把父類型的 this 指向子類型的 this,這樣就可以實現子類型繼承父類型的屬性

<body>
    <script>
        // 借用父構造函數繼承屬性
        // 1. 父構造函數
        function Father(uname, age) {
            // this 指向父構造函數的對象實例
            this.uname = uname;
            this.age = age;
        }
        // 2 .子構造函數 
        function Son(uname, age, score) {
            // this 指向子構造函數的對象實例
            Father.call(this, uname, age);
            this.score = score;
        }
        var son = new Son('劉德華', 18, 100);
        console.log(son);
    </script></body>

3.3、借用原型對象繼承父類型方法

  • 一般情況下,對象的方法都在構造函數的原型對象中設置,通過構造函數無法繼承父類方法

核心原理:

  1. 將子類所共享的方法提取出來,讓子類的 prototype 原型對象 = new 父類()

  2. 本質: 子類原型對象等于是實例化父類,因為父類實例化之后另外開辟空間,就不會影響原來父類原型對象

  3. 將子類的constructor重新指向子類的構造函數

<body>
    <script>
        // 借用父構造函數繼承屬性
        // 1. 父構造函數
        function Father(uname, age) {
            // this 指向父構造函數的對象實例
            this.uname = uname;
            this.age = age;
        }
        Father.prototype.money = function() {
            console.log(100000);

        };
        // 2 .子構造函數 
        function Son(uname, age, score) {
            // this 指向子構造函數的對象實例
            Father.call(this, uname, age);
            this.score = score;
        }
        // Son.prototype = Father.prototype;  這樣直接賦值會有問題,如果修改了子原型對象,父原型對象也會跟著一起變化
        Son.prototype = new Father();
        // 如果利用對象的形式修改了原型對象,別忘了利用constructor 指回原來的構造函數
        Son.prototype.constructor = Son;
        // 這個是子構造函數專門的方法
        Son.prototype.exam = function() {
            console.log('孩子要考試');

        }
        var son = new Son('劉德華', 18, 100);
        console.log(son);
        console.log(Father.prototype);
        console.log(Son.prototype.constructor);
    </script></body>

3.3 類的本質

  1. class 本質還是 function

  2. 類的所有方法都定義在類的 prototype屬性上

  3. 類創建的實例,里面也有_proto_指向類的prototype原型對象

  4. 所以 ES6 的類它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。

  5. 所以 ES6 的類其實就是語法糖

  6. 語法糖:語法糖就是一種便捷寫法,簡單理解

4、ES5新增方法

ES5 給我們新增了一些方法,可以很方便的操作數組或者字符串

  • 數組方法

  • 字符串方法

  • 對象方法

4.1、數組方法

  • 迭代(遍歷)方法:foreach() ,map(),filter(),some() ,every() ;

4.1.1、forEach()

array.forEach(function(currentValue,index,arr))
  • currentValue: 數組當前項的值

  • index: 數組當前項的索引

  • arr: 數組對象本身

<body>
    <script>
        // forEach 迭代(遍歷) 數組
        var arr = [1, 2, 3];
        var sum = 0;
        arr.forEach(function(value, index, array) {
            console.log('每個數組元素' + value);
            console.log('每個數組元素的索引號' + index);
            console.log('數組本身' + array);
            sum += value;
        })
        console.log(sum);
    </script></body>

4.1.2、filter()篩選數組

array.filter(function(currentValue,index,arr))
  • filter()方法創建一個新的數組,新數組中的元素是通過檢查指定數組中符合條件的所有元素,主要用于篩選數組

  • 注意它直接返回一個新數組

<body>
    <script>
        // filter 篩選數組
        var arr = [12, 66, 4, 88, 3, 7];
        var newArr = arr.filter(function(value, index) {
            // return value >= 20;
            return value % 2 === 0;
        });
        console.log(newArr);
    </script></body>

4.1.3、some()

  • some()方法用于檢測數組中的元素是否滿足指定條件(查找數組中是否有滿足條件的元素)

  • 注意它返回的是布爾值,如果查找到這個元素,就返回true,如果查找不到就返回false

  • 如果找到第一個滿足條件的元素,則終止循環,不再繼續查找

<body>
    <script>
        // some 查找數組中是否有滿足條件的元素 
        var arr1 = ['red', 'pink', 'blue'];
        var flag1 = arr1.some(function(value) {
            return value == 'pink';
        });
        console.log(flag1);
        // 1. filter 也是查找滿足條件的元素 返回的是一個數組 而且是把所有滿足條件的元素返回回來
        // 2. some 也是查找滿足條件的元素是否存在  返回的是一個布爾值 如果查找到第一個滿足條件的元素就終止循環
    </script></body>

4.2、字符串方法

  • trim()方法會從一個字符串的兩端刪除空白字符

  • trim()方法并不影響原字符串本身,它返回的是一個新的字符串

<body>
    <input type="text"> <button>點擊</button>
    <p></p>
    <script>
        // trim 方法去除字符串兩側空格
        var str = '   an  dy   ';
        console.log(str);
        var str1 = str.trim();
        console.log(str1);
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var p = document.querySelector('p');
        btn.onclick = function() {
            var str = input.value.trim();
            if (str === '') {
                alert('請輸入內容');
            } else {
                console.log(str);
                console.log(str.length);
                p.innerHTML = str;
            }
        }
    </script></body>

4.3、對象方法

4.3.1、Object.keys()

  1. Object.keys()用于獲取對象自身所有的屬性

  2. 效果類似for...in

  3. 返回一個由屬性名組成的數組

<body>
    <script>
        // 用于獲取對象自身所有的屬性
        var obj = {
            id: 1,
            pname: '小米',
            price: 1999,
            num: 2000
        };
        var arr = Object.keys(obj);
        console.log(arr);
        arr.forEach(function(value) {
            console.log(value);
            // id
            // pname
            // price
            // num
        })
    </script></body>

4.3.2、Object.defineProperty()

  • Object.defineProperty()定義對象中新屬性或修改原有的屬性(了解)

Object.defineProperty(obj,prop,descriptor)
  • obj : 目標對象

  • prop : 需定義或修改的屬性的名字

  • descriptor : 目標屬性所擁有的特性

<body>
    <script>
        // Object.defineProperty() 定義新屬性或修改原有的屬性
        var obj = {
            id: 1,
            pname: '小米',
            price: 1999
        };
        // 1. 以前的對象添加和修改屬性的方式
        // obj.num = 1000;
        // obj.price = 99;
        // console.log(obj);
        // 2. Object.defineProperty() 定義新屬性或修改原有的屬性
        Object.defineProperty(obj, 'num', {
            value: 1000,
            enumerable: true
        });
        console.log(obj);
        Object.defineProperty(obj, 'price', {
            value: 9.9
        });
        console.log(obj);
        Object.defineProperty(obj, 'id', {
            // 如果值為false 不允許修改這個屬性值 默認值也是false
            writable: false,
        });
        obj.id = 2;
        console.log(obj);
        Object.defineProperty(obj, 'address', {
            value: '中國山東藍翔技校xx單元',
            // 如果只為false 不允許修改這個屬性值 默認值也是false
            writable: false,
            // enumerable 如果值為false 則不允許遍歷, 默認的值是 false
            enumerable: false,
            // configurable 如果為false 則不允許刪除這個屬性 不允許在修改第三個參數里面的特性 默認為false
            configurable: false
        });
        console.log(obj);
        console.log(Object.keys(obj));
        delete obj.address;
        console.log(obj);
        delete obj.pname;
        console.log(obj);
        Object.defineProperty(obj, 'address', {
            value: '中國山東藍翔技校xx單元',
            // 如果值為false 不允許修改這個屬性值 默認值也是false
            writable: true,
            // enumerable 如果值為false 則不允許遍歷, 默認的值是 false
            enumerable: true,
            // configurable 如果為false 則不允許刪除這個屬性 默認為false
            configurable: true
        });
        console.log(obj.address);
    </script></body>
  • 第三個參數 descriptor 說明:以對象形式{ }書寫

  • value:設置屬性的值,默認為undefined

  • writeable: 值是否可以重寫 true | false 默認為false

  • enumerable: 目標屬性是否可以被枚舉 true | false 默認為false

  • configurable: 目標屬性是否可以被刪除或是否可以再次修改特性 true | false 默認為false

5、函數進階

5.1、函數的定義方式

  1. 函數聲明方式 function 關鍵字(命名函數)

  2. 函數表達式(匿名函數)

  3. new Function()

var fn = new Function('參數1','參數2',.....,'函數體');
  • Function 里面參數都必須是字符串格式

  • 第三種方式執行效率低,也不方便書寫,因此較少使用

  • 所有函數都是 Function 的實例(對象)

  • 函數也屬于對象

JavaScript面向對象的思維特點是什么

<body>
    <script>
        //  函數的定義方式

        // 1. 自定義函數(命名函數) 

        function fn() {};

        // 2. 函數表達式 (匿名函數)

        var fun = function() {};


        // 3. 利用 new Function('參數1','參數2', '函數體');
		//             Function 里面參數都必須是字符串格式,執行效率低,較少寫

        var f = new Function('a', 'b', 'console.log(a + b)');
        f(1, 2);
        // 4. 所有函數都是 Function 的實例(對象)
        console.dir(f);
        // 5. 函數也屬于對象
        console.log(f instanceof Object);
    </script></body>

5.2、函數的調用方式

  1. 普通函數

  2. 對象的方法

  3. 構造函數

  4. 綁定事件函數

  5. 定時器函數

  6. 立即執行函數

<body>
    <script>
        // 函數的調用方式

        // 1. 普通函數
        function fn() {
            console.log('人生的巔峰');

        }
        // fn();   fn.call()
        // 2. 對象的方法
        var o = {
            sayHi: function() {
                console.log('人生的巔峰');

            }
        }
        o.sayHi();
        // 3. 構造函數
        function Star() {};
        new Star();
        // 4. 綁定事件函數
        // btn.onclick = function() {};   // 點擊了按鈕就可以調用這個函數
        // 5. 定時器函數
        // setInterval(function() {}, 1000);  這個函數是定時器自動1秒鐘調用一次
        // 6. 立即執行函數
        (function() {
            console.log('人生的巔峰');
        })();
        // 立即執行函數是自動調用
    </script></body>

5.3、函數內this的指向

  • this指向,是當我們調用函數的時候確定的,調用方式的不同決定了this的指向不同,一般我們指向我們的調用者

調用方式this指向
普通函數調用window
構造函數調用實例對象,原型對象里面的方法也指向實例對象
對象方法調用該方法所屬對象
事件綁定方法綁定事件對象
定時器函數window
立即執行函數window
<body>
    <button>點擊</button>
    <script>
        // 函數的不同調用方式決定了this 的指向不同
        // 1. 普通函數 this 指向window
        function fn() {
            console.log('普通函數的this' + this);
        }
        window.fn();
        // 2. 對象的方法 this指向的是對象 o
        var o = {
            sayHi: function() {
                console.log('對象方法的this:' + this);
            }
        }
        o.sayHi();
        // 3. 構造函數 this 指向 ldh 這個實例對象 原型對象里面的this 指向的也是 ldh這個實例對象
        function Star() {};
        Star.prototype.sing = function() {

        }
        var ldh = new Star();
        // 4. 綁定事件函數 this 指向的是函數的調用者 btn這個按鈕對象
        var btn = document.querySelector('button');
        btn.onclick = function() {
            console.log('綁定時間函數的this:' + this);
        };
        // 5. 定時器函數 this 指向的也是window
        window.setTimeout(function() {
            console.log('定時器的this:' + this);

        }, 1000);
        // 6. 立即執行函數 this還是指向window
        (function() {
            console.log('立即執行函數的this' + this);
        })();
    </script></body>

5.4、改變函數內部this指向

  • JavaScript 為我們專門提供了一些函數方法來幫我們處理函數內部 this 的指向問題,常用的有 bind(),call(),apply()三種方法

5.4.1、call() 方法

  • call()方法調用一個對象,簡單理解為調用函數的方式,但是它可以改變函數的this指向

  • fun.call(thisArg,arg1,arg2,.....)

  • thisArg: 在 fun 函數運行時指定的 this 值

  • arg1,arg2: 傳遞的其他參數

  • 返回值就是函數的返回值,因為它就是調用函數

  • 因此當我們想改變 this 指向,同時想調用這個函數的時候,可以使用 call,比如繼承

<body>
    <script>
        // 改變函數內this指向  js提供了三種方法  call()  apply()  bind()

        // 1. call()
        var o = {
            name: 'andy'
        }

        function fn(a, b) {
            console.log(this);
            console.log(a + b);

        };
        fn.call(o, 1, 2);
        // call 第一個可以調用函數 第二個可以改變函數內的this 指向
        // call 的主要作用可以實現繼承
        function Father(uname, age, sex) {
            this.uname = uname;
            this.age = age;
            this.sex = sex;
        }

        function Son(uname, age, sex) {
            Father.call(this, uname, age, sex);
        }
        var son = new Son('劉德華', 18, '男');
        console.log(son);
    </script></body>

5.4.2、apply()方法

  • apply()方法調用一個函數,簡單理解為調用函數的方式,但是它可以改變函數的 this指向

  • fun.apply(thisArg,[argsArray])

  • thisArg: 在 fun 函數運行時指定的 this 值

  • argsArray : 傳遞的值,必須包含在數組里面

  • 返回值就是函數的返回值,因為它就是調用函數

  • 因此 apply 主要跟數組有關系,比如使用 Math.max() 求數組的最大值

<body>
    <script>
        // 改變函數內this指向  js提供了三種方法  call()  apply()  bind()

        // 2. apply()  應用 運用的意思
        var o = {
            name: 'andy'
        };

        function fn(arr) {
            console.log(this);
            console.log(arr); // 'pink'

        };
        fn.apply(o, ['pink']);
        // 1. 也是調用函數 第二個可以改變函數內部的this指向
        // 2. 但是他的參數必須是數組(偽數組)
        // 3. apply 的主要應用 比如說我們可以利用 apply 借助于數學內置對象求數組最大值 
        // Math.max();
        var arr = [1, 66, 3, 99, 4];
        var arr1 = ['red', 'pink'];
        // var max = Math.max.apply(null, arr);
        var max = Math.max.apply(Math, arr);
        var min = Math.min.apply(Math, arr);
        console.log(max, min);
    </script></body>

5.4.3、bind()方法

  • bind()方法不會調用函數。但是能改變函數內部 this指向

  • fun.bind(thisArg,arg1,arg2,....)

  • 返回由指定的 this值和初始化參數改造的原函數拷貝

  • 因此當我們只是想改變 this 指向,并且不想調用這個函數的時候,可以使用bind

<body>
    <button>點擊</button>
    <button>點擊</button>
    <button>點擊</button>
    <script>
        // 改變函數內this指向  js提供了三種方法  call()  apply()  bind()

        // 3. bind()  綁定 捆綁的意思
        var o = {
            name: 'andy'
        };

        function fn(a, b) {
            console.log(this);
            console.log(a + b);


        };
        var f = fn.bind(o, 1, 2);
        f();
        // 1. 不會調用原來的函數   可以改變原來函數內部的this 指向
        // 2. 返回的是原函數改變this之后產生的新函數
        // 3. 如果有的函數我們不需要立即調用,但是又想改變這個函數內部的this指向此時用bind
        // 4. 我們有一個按鈕,當我們點擊了之后,就禁用這個按鈕,3秒鐘之后開啟這個按鈕
        // var btn1 = document.querySelector('button');
        // btn1.onclick = function() {
        //     this.disabled = true; // 這個this 指向的是 btn 這個按鈕
        //     // var that = this;
        //     setTimeout(function() {
        //         // that.disabled = false; // 定時器函數里面的this 指向的是window
        //         this.disabled = false; // 此時定時器函數里面的this 指向的是btn
        //     }.bind(this), 3000); // 這個this 指向的是btn 這個對象
        // }
        var btns = document.querySelectorAll('button');
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function() {
                this.disabled = true;
                setTimeout(function() {
                    this.disabled = false;
                }.bind(this), 2000);
            }
        }
    </script></body>

5.4.4、總結

call apply bind 總結:

相同點:

  • 都可以改變函數內部的 this指向

區別點:

  • callapply會調用函數,并且改變函數內部的this指向

  • callapply傳遞的參數不一樣,call 傳遞參數,apply 必須數組形式

  • bind不會調用函數,可以改變函數內部this指向

主要應用場景

  1. call經常做繼承

  2. apply經常跟數組有關系,比如借助于數學對線實現數組最大值與最小值

  3. bind不調用函數,但是還想改變this指向,比如改變定時器內部的this指向

以上就是關于“JavaScript面向對象的思維特點是什么”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泽普县| 谷城县| 兴和县| 尼玛县| 忻城县| 平潭县| 武邑县| 拜城县| 建瓯市| 土默特左旗| 罗江县| 邓州市| 剑川县| 山阴县| 新化县| 梁河县| 基隆市| 灌云县| 武冈市| 垫江县| 本溪| 澳门| 绩溪县| 宁波市| 阿拉善盟| 高尔夫| 安平县| 大庆市| 石楼县| 微山县| 阳曲县| 永新县| 昌乐县| 乌海市| 汤原县| 兴义市| 蕉岭县| 临江市| 曲麻莱县| 荔波县| 辽源市|