欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript知識:構造函數(shù)也是函數(shù)

 更新時間:2021年08月20日 10:30:53   作者:峰回路轉~  
構造函數(shù)就是初始化一個實例對象,對象的prototype屬性是繼承一個實例對象。本文給大家分享javascript構造函數(shù)詳解,對js構造函數(shù)相關知識感興趣的朋友一起學習吧

首先要明確的是構造函數(shù)也是函數(shù)

我經(jīng)常使用構造函數(shù)來創(chuàng)建實例對象,例如對象和數(shù)組的實例化可以通過相應的構造函數(shù)Object()和Array()完成。

構造函數(shù)與普通函數(shù)在語法的定義上沒有任何區(qū)別,主要的區(qū)別體現(xiàn)在以下3點。

(1)構造函數(shù)的函數(shù)名的第一個字母通常會大寫。按照慣例,構造函數(shù)名稱的首字母都是要大寫的,非構造函數(shù)則以小寫字母開頭。這是從面向對象編程語言那里借鑒的,有助于在ECMAScript中區(qū)分構造函數(shù)和普通函數(shù)。

(2)在函數(shù)體內(nèi)部使用this關鍵字,表示要生成的對象實例,構造函數(shù)并不會顯式地返回任何值,而是默認返回“this”。在下面的代碼段中,Person()函數(shù)并沒有使用return關鍵字返回任何信息,但是輸出的變量person1是一個具有name、age屬性值的Person實例。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
      //1.定義構造函數(shù)
      function Person(name,age){
        this.age = age;
        this.name = name;
        this.sayName = function(){
            console.log(this.name);
        } 
      }
      // 2.生成實例對象
      var person1 = new Person('小蘇','18');
      // 3.打印實例對象
      console.log(person1);
  </script>
</body>
</html>

顯示效果如下


(3)作為構造函數(shù)調用時,必須與new操作符配合使用。這一點非常重要,任何函數(shù)只要使用new操作符調用就是構造函數(shù),而不使用new操作符調用的函數(shù)就是普通函數(shù)。

1、構造函數(shù)的定義與調用

構造函數(shù)又稱為自定義函數(shù),以函數(shù)的形式為自己的對象類型定義屬性和方法。

舉例:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
      //1.定義構造函數(shù)
      function Person(name,age){
        this.age = age;
        this.name = name;
        this.sayName = function(){
            console.log(this.name);
        } 
      }
      // 2.生成實例對象
      var person1 = new Person('小蘇','18');
      // 3.調用方法
      person1.sayName();
  </script>
</body>
</html>

2、new關鍵字的用途

構造函數(shù)在執(zhí)行時,會執(zhí)行以下4步:

  • 通過new關鍵字(操作符)創(chuàng)建實例對象,會在內(nèi)存中創(chuàng)建一個新的地址。
  • 為構造函數(shù)中的this確定指向,指向實例的本身。
  • 執(zhí)行構造函數(shù)代碼,為實例添加屬性。
  • 返回這個新創(chuàng)建的對象。

以前面生成person1實例的代碼為例。

第一步:為person1實例在內(nèi)存中創(chuàng)建一個新的地址。

第二步:確定person1實例的this指向,指向person本身。

第三步:為person1實例添加name、age和sayName屬性,其中sayName屬性值是一個函數(shù)。

第四步:返回這個person1實例。

舉個實例

var person1 = new Person("Bob", 18);

這行代碼,等價于

// 演示 new 的功能
function Person(name,age) {
  // 1.創(chuàng)建一個新對象
  var instance = new Object();
  // 2.將函數(shù)內(nèi)部的 this 指向了這個新對象
  this = instance;
  // 3.執(zhí)行構造函數(shù)內(nèi)部的代碼
  this.name = name;
  this.age = age;
  this.sayName = function () {
    console.log(this.name);
  };
  // 4.將新對象作為返回值
  return instance;
}

這就意味著,將instance 賦值給 person1,即person1 = instance。實際上又是這樣的:

// 演示 new 的功能
function Person(name,age) {
  // 1.創(chuàng)建一個新對象
  var person1 = new Object();
  // 2.將函數(shù)內(nèi)部的 this 指向了這個新對象
  this = person1;
  // 3.執(zhí)行構造函數(shù)內(nèi)部的代碼
  this.name = name;
  this.age = age;
  this.sayName = function () {
    console.log(this.name);
  };
  // 4.將新對象作為返回值
  return person1;
}

3、構造函數(shù)的問題:浪費內(nèi)存

基本事實:不同實例中的sayName屬性是不同的。舉個例子:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 1.自定義構造函數(shù)
    function Person(name,age) {
      this.name = name;
      this.age = age;
      // this 內(nèi)部的 type 屬性值是不變的
      this.type = "human";
      // 每個對象的 sayName 方法也是一樣的
      this.sayName = function () {
        console.log(this.name);
      };
    }
    
    var person1 = new Person('Bob',18);
    var person2 = new Person('Mike',20);
    // 2,判斷各自的方法是否是同一個函數(shù)
    console.log(person1.sayName === person2.sayName); // false
  </script>
</body>
</html>

解釋:通過console.log(person1.sayName === person2.sayName)方法可判斷兩個函數(shù)是否是是同一個,顯然這不是同一個函數(shù),那么兩個函數(shù)就占用了兩個內(nèi)存空間,就會造成內(nèi)存的浪費。

那如何解決函數(shù)占用內(nèi)存的辦法呢?答案是將對象內(nèi)部函數(shù)提取出來作為公共函數(shù)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 解決方法1: 將公共的函數(shù)提取到構造函數(shù)之外
    function sayName() {
      console.log(this.name);
    }
    function sayAge() {
      console.log(this.age);
    }
    //1.自定義對象
    function Person(name,age) {
      this.name = name;
      this.age = age;
      // this 內(nèi)部的 type 屬性值是不變的
      this.type = "human";
      // 每個對象的 sayName 方法也是一樣的
      this.sayName = sayName;
      this.sayAge = sayAge;
    }
    //2.實例化對象
    var person1 = new Person('Bob',18);
    var person2 = new Person('Mike',20);
    console.log(person1.sayName === person2.sayName); // true
    </script>
</body>
</html>

此時,也存在一個問題,如果有多個公共函數(shù),需要在外部創(chuàng)建多個函數(shù),可能會造成命名沖突

解決辦法,將多個公共的函數(shù)封裝到一個對象

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    // 3.將多個公共的函數(shù)封裝到一個對象
    var fns = {
      sayName : function () {
        console.log(this.name);
      },
      sayAge : function () {
        console.log(this.age);
      }      
    };    
    // 1.自定義對象
    function Person(name,age) {
      this.name = name;
      this.age = age;
      this.type = "human";
      this.sayName = fns.sayName;
      this.sayAge = fns.sayAge;
    }
    // 2.生成對象實例
    var person1 = new Person("Bob",18);
    var person2 = new Person("Mike",20);

    // person1.sayName();
    console.log(person1.sayName === person2.sayName);
    console.log(person1.sayAge === person2.sayAge);
  </script>
</body>
</html>

解釋:將多個函數(shù)封裝成一個對象即可解決函數(shù)名可能沖突的問題。

通過這種設置全局訪問的函數(shù),這樣就可以被所有實例訪問到,而不用重復創(chuàng)建。

但是這樣也會存在一個問題,如果為一個對象添加的所有函數(shù)都處理成全局函數(shù),這樣并無法完成對一個自定義類型對象的屬性封裝(言外之意。指的是全局函數(shù)只可以封裝函數(shù),但無法封裝屬性,因為屬性封裝在函數(shù)外面,要定義為全局變量,才可以去調用,這反而會污染全局變量),因此這不是一個好的解決辦法。

此時,便引用原型的概念,使用原型概念可以很好解決這個問題,可以很好解決這個問題。

總結

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!

相關文章

最新評論