【JavaScript高級】構造函數、原型鏈與數據處理

目錄

  • 構造函數和原型
    • 構造函數
    • 實例成員和靜態成員
    • 構造函數的問題
    • 構造函數原型 prototype
    • 對象原型 \_\_proto\_\_
    • constructor 構造函數
    • 構造函數、實例、原型對象三者之間的關系
    • 原型鏈
    • JavaScript 的成員查找機制(規則)
    • 原型對象的this指向
    • 擴展內置對象
  • 繼承
    • call()
    • 借用構造函數繼承父類型屬性
    • 借用原型對象繼承父類型方法
  • 類的本質
  • ES5中新增的方法
    • 數組方法
    • 字符串方法
    • Object.defineProperty方法
    • 對象方法

構造函數和原型

構造函數

構造函數是一種特殊的函數,主要用來初始化對象,即為對象成員變量賦初始值,它總與new一起使用。我們可以把對象中一些公共的屬性和方法抽取出來,然后封裝到這個函數里面。

值得注意的點:

  1. 構造函數用于創建某一類對象,其首字母要大寫
  2. 構造函數要和new一起使用才有意義

new在執行時會做如下四件事情:

  1. 在內存中創建一個新的空對象
  2. 讓this指向這個新的對象
  3. 執行構造函數里面的代碼,給這個新對象添加屬性和方法。
  4. 返回這個新對象(所以構造函數里面不需要return)

實例成員和靜態成員

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

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

構造函數的問題

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

class Student{constructor(sname,sgender){this.sname = sname;this.sgender = sgender;this.sayHello = function(){console.log("你好我是"+this.sname+",我的性別是"+this.sgender);}}}
var s1 = new Student("張三","男");
var s2 = new Student("李四","女");
s1.sayHello();//你好我是張三,我的性別是男
s2.sayHello(); //你好我是李四,我的性別是女

在這里插入圖片描述
上面的代碼中每一個實例化對象都會對應一個內存空間但是使用的是同樣的函數,存在內存浪費。
我們希望所有的對象使用同一個函數,這樣就比較節省內存,那要怎么做呢。

構造函數原型 prototype

構造函數通過原型分配的函數是所有對象所共享的
JavaScript規定,每一個構造函數都有一個prototype屬性,指向另一個對象。注意這個prototype就是一個對象,這個對象的所有屬性和方法,都會被構造函數所擁有。

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}Student.prototype.sayHello = function () {console.log("你好我是" + this.sname + ",我的性別是" + this.sgender);
}var s1 = new Student("張三", "男");
var s2 = new Student("李四", "女");
s1.sayHello(); // 你好我是張三,我的性別是男
s2.sayHello(); // 你好我是李四,我的性別是女

對象原型 __proto__

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

  • __proto__對象原型和原型對象prototype是等價的
  • __proto__對象原型的意義就在于為對象的查找機制提供一個方向,或者說一條路線,但是它是一個非標準屬性,因此實際開發中,不可以使用這個屬性,它只是內部指向原型對象prototype
console.log(s1.__proto__ === Student.prototype); // true

在這里插入圖片描述

constructor 構造函數

對象原型(__proto__)和構造函數(prototype)原型對象里面都有一個屬性constructor屬性,constructor我們稱為構造函數,因為它指回構造函數本身。
constructor主要用于記錄該對象引用于哪個構造函數,它可以讓原型對象重新指向原來的構造函數。
如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用construct指回原來的構造函數。

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}Student.prototype = {constructor: Student,// 修復構造函數指向問題sayHello: function () {console.log("你好我是" + this.sname + ",我的性別是" + this.sgender);},sayBye: function () {console.log("再見!");}
}
var s1 = new Student("張三", "男");
s1.sayHello(); // 你好我是張三,我的性別是男
s1.sayBye(); // 再見!

構造函數、實例、原型對象三者之間的關系

在這里插入圖片描述

原型鏈

每個構造函數都有 prototype 屬性,該屬性指向其原型對象。原型對象的__proto__指向 Object.prototype,也就是 Object 的原型對象。Object.prototype 由 Object 構造函數創建,它是所有對象原型鏈的終點,其__proto__為 null,意味著原型鏈到此終止。

在這里插入圖片描述

JavaScript 的成員查找機制(規則)

  1. 當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性
  2. 如果沒有就查找它的原型(也就是__proto__指向的prototype原型對象
  3. 如果還沒有就查找原型對象的原型(Object的原型對象
  4. 以此類推一直找到Object為止(null
  5. __proto__對象原型的意義就是在于為對象成員查找機制提供一個方向或者說一條路線

原型對象的this指向

通過如下的代碼可以得出結論:無論是構造函數中的this還是原型對象函數中的this指向的都是對象實例

function Student(sname, sgender) {this.sname = sname;this.sgender = sgender;
}var that;
Student.prototype.sayHello = function () {console.log("你好我是" + this.sname + ",我的性別是" + this.sgender);that = this;
}
var s1 = new Student("張三", "男");
// 在構造函數中,里面this指向的是對象實例s1
s1.sayHello(); // 你好我是張三,我的性別是男
console.log(that === s1); //true
// 原型對象函數里面的this指向的是對象實例s1

擴展內置對象

可以通過原型對象,對原來的內置對象進行擴展自定義的方法。比如給數組增加自定義求和的功能。
注意:數組和字符串內置對象不能給原型對象覆蓋操作Array.prototype={},只能是Array.prototype.xxx=function(){}的方式。

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, 4, 5];
console.log(arr.sum()); // 15
var arr1 = new Array(1, 2, 3, 4, 5);
console.log(arr1.sum()); // 15

繼承

ES6之前并沒有給我們提供extends繼承。我們可以通過構造函數+原型對象模擬實現繼承,被稱為組合繼承

call()

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

fun.call(thisArg,arg1,arg2,...)
  • thisArg:當前調用函數this的指向對象
  • arg1,arg2:傳遞的其他參數
function fn() {console.log("hello world");console.log(this);
}
var obj = {name: "obj"
};
// 1.call() 可以調用函數
fn.call(); // window{...}
// 2.call() 可以改變函數的this指向
fn.call(obj); // obj{name: "obj"}

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

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

//借用父構造函數繼承屬性
//1.父構造函數
function Parent(name, age) {//this指向父構造函數的實例對象this.name = name;this.age = age;
}
//2.子構造函數
function Child(name, age) {//this指向子構造函數的實例對象Parent.call(this, name, age); //借用父構造函數繼承屬性// Parent.apply(this, arguments); //借用父構造函數繼承屬性,使用apply可以傳入任意數量的參數
}
//3.創建子構造函數的實例對象
var child = new Child('小明', 18);
console.log(child.name); //小明
console.log(child.age); //18

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

//1.父構造函數
function Parent(name, age) {this.name = name;this.age = age;
}
Parent.prototype.money = function () {console.log(100000);
}//2.子構造函數
function Child(name, age) {Parent.call(this, name, age); //借用父構造函數繼承屬性
}
// Child.prototype = Parent.prototype; //這樣直接賦值會有問題,如果修改了子原型對象,如果修改了子原型對象,父原型對象也會被修改
Child.prototype = new Parent(); //借用父構造函數的原型對象
//如果利用對象的形式修改了原型對象,別忘了利用constructor指回原來的構造函數
Child.prototype.constructor = Child;
//3.創建子構造函數的實例對象
var child = new Child('小明', 18);
console.log(child.name); //小明
console.log(child.age); //18
child.money(); //100000

類的本質

  1. class本質還是function
  2. 類的所有方法都定義在類的prototype屬性上
  3. 類創建的實例,里面也有__proto__指向類的prototype原型對象
  4. 所以ES6的類它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已
  5. 所以ES6的類其實就是語法糖
class Student{}
//1. 類的本質其實還是一個函數 我們也可以簡單的認為類就是構造函數的另外一種寫法
console.log(typeof Student);// "function"
//(1).類有原型對象prototype
console.log(Student.prototype);// {constructor: ?}
//(2).類原型對象prototype里面有constructor指向類本身
console.log(Student.prototype.constructor);// ? Student() { [native code] }
//(3).類可以通過原型對象添加方法
Student.prototype.sayHello = function(){console.log("Hello, I am a student.");
}
var s = new Student();
console.dir(s);
//(4)構造函數創建的實例對象有__proto__屬性指向類原型對象prototype
console.log(s.__proto__ === Student.prototype);

ES5中新增的方法

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

數組方法

迭代(遍歷)方法:forEach()、map()、filter()、some()、every()

  1. forEach()方法

    • 用于遍歷數組中的每個元素
    • 不會改變原數組
    • 默認三個回調參數為value、index、array
    • 示例:[1,2,3].forEach(function(value){console.log(value)})
  2. map()方法

    • 對數組中的每個元素執行回調函數
    • 返回一個新數組
    • 示例:[1,2,3].map(function(value){return value*2})返回[2,4,6]
  3. filter()方法

    • 篩選數組中符合條件的元素
    • 返回一個新數組
    • 示例:[1,2,3].filter(function(value){return value>1})返回[2,3]
  4. some()方法

    • 檢測數組中是否有元素滿足條件
    • 返回布爾值
    • 示例:[1,2,3].some(function(value){return value>2})返回true
  5. every()方法

    • 檢測數組中的所有元素是否都滿足條件
    • 返回布爾值
    • 示例:[1,2,3].every(function(value){return value>0})返回true

字符串方法

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

Object.defineProperty方法

Object.defineProperty(obj, prop ,descriptor)
  • obj:必需,目標對象
  • prop:必需,需定義或修改的屬性的名字
  • descriptor:必需,目標屬性所擁有的特性
    第三個參數descriptor說明:以對象形式{ }書寫
  • value:設置屬性的值,默認為undefined
  • weitable:值是否可以重寫。true|false 默認為false
  • enumerable:目標屬性是否可以被枚舉 true|false 默認為false
  • configurable:目標屬性是否可以被刪除或是否可以再次修改特性 true|false 默認為false
var obj = {name: 'zhangsan',age: 20 
};Object.defineProperty(obj, 'gender', {value: 'male',writable: true,enumerable: true,configurable: true
});console.log(obj); // {name: "zhangsan", age: 20, gender: "male"}

對象方法

  1. Object.keys()用于獲取對象自身所有的屬性
object.keys(obj)
  • 效果類似for…in
  • 返回一個由屬性名組成的數組

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88997.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88997.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88997.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

項目進度與預算脫節,如何進行同步管理

項目進度與預算脫節會導致資源浪費、成本超支和項目延期。進行同步管理的方法包括&#xff1a;建立統一的項目進度預算管理體系、實施實時監控與反饋機制、采用項目管理工具輔助同步管理。尤其是實施實時監控與反饋機制&#xff0c;通過持續監測進度與預算的匹配情況&#xff0…

TCP半關閉

理解TCP半關閉&#xff1a;像水管一樣的網絡連接控制 從全關閉到半關閉&#xff1a;為什么需要這種機制&#xff1f; 想象你和朋友正在通電話討論一個重要項目&#xff1a; 全關閉&#xff1a;就像突然掛斷電話&#xff0c;雙方都無法再說話半關閉&#xff1a;你說"我說完…

衡石科技技術手冊--儀表盤過濾控件詳解

過濾控件說明 過濾控件 的定義 過濾控件用于在儀表盤中過濾圖表數據&#xff0c;分為儀表盤內過濾控件和全局過濾控件。 過濾控件結構說明 字段類型描述uidSTRING過濾控件唯一識別 idappIdLONG過濾控件所屬的應用 iddataAppIdLONG字段來源是數據包時的數據包 iddashboar…

ASP.NET Core中數據綁定原理實現詳解

在ASP.NET Core 中&#xff0c;數據綁定是將 HTTP 請求中的數據&#xff08;如表單、查詢字符串、請求體等&#xff09;映射到控制器動作方法參數或模型對象的過程。以下將從原理、核心組件、執行流程及關鍵機制等方面詳細解析其實現邏輯。 一、數據綁定的核心原理與組件 1. 數…

牛客:HJ24 合唱隊[華為機考][最長遞增子集][動態規劃]

學習要點 求最長遞增字列求最長遞減子列 題目鏈接 合唱隊_牛客題霸_牛客網 題目描述 解法&#xff1a;動歸求最長遞增子列 #include <iostream> #include <vector> using namespace std;int main() {int n;while (cin >> n) {// 輸入的數組int tmp;vect…

C語言的相關基礎概念和常用基本數據類型

1.相關概念變量與常量的定義常量&#xff1a;在程序運行中其值不能改變的量。變量&#xff1a;在程序運行中其值可以改變的量。存儲器的區分 RAMROM中文名易失存儲器不易失存儲器特點掉電丟失數據&#xff0c;但存取快掉電不丟失數據&#xff0c;但存取幔標識符標識符只能…

Spring boot整合dubbo+zookeeper

Spring boot整合dubbozookeeper 下文將簡述springboot整合dubbozookeeper實現apiproviderconsumer模式&#xff0c;Api用于定于interface,provider和consumer依賴Api,provider實現api接口&#xff0c;consumer調用provider。 spring boot版本&#xff1a;3.5.3 jdk版本&#xf…

ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32‘ not found

簡介&#xff1a;在復現 VLM-R1 項目并嘗試將其中的 GRPO 算法應用到自己的任務時&#xff0c;按照官方文檔配置好環境后&#xff0c;運行過程中遇到了一個非常離譜的錯誤&#xff1a; ImportError: /lib/x86_64-linux-gnu/libc.so.6: version GLIBC_2.32 not found 這個問題極…

基于Spring Boot的生活用品電商網站的設計與實現

第1章 摘要隨著電商行業的飛速發展&#xff0c;生活用品電商網站作為線上購物的一部分&#xff0c;逐漸成為消費者日常購物的重要渠道。為提升網站的管理效率和用戶體驗&#xff0c;設計并實現了一款基于Spring Boot的生活用品電商網站。該系統通過合理的架構設計&#xff0c;提…

數據結構 單鏈表(1)

1.概念和結構概念&#xff1a;鏈表是一種物理存儲結構上非連續、非順序的存儲結構&#xff0c;數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。通過指針鏈接次序實現的要怎么理解呢?這是一張鏈表的結構圖:與順序表不同的是&#xff0c;鏈表里的每節“車廂” (仔細觀察這…

Python爬蟲實戰:研究PyMongo庫相關技術

1. 引言 在當今信息爆炸的時代,互聯網上存在著海量的有價值數據。如何高效地獲取這些數據并進行存儲和分析,成為了數據科學領域的重要研究方向。網絡爬蟲作為一種自動化的數據采集工具,可以幫助我們從網頁中提取所需的信息。而 MongoDB 作為一種流行的 NoSQL 數據庫,能夠靈…

【世紀龍科技】邁騰B8汽車整車檢測與診斷仿真實訓系統

在汽車技術日新月異的今天&#xff0c;如何培養既懂理論又精實踐的高素質汽修人才&#xff0c;成為職業教育領域亟待突破的課題。江蘇世紀龍科技憑借深厚的技術積淀與教育洞察&#xff0c;重磅推出《汽車整車檢測與診斷仿真實訓系統》&#xff0c;以邁騰B8為原型&#xff0c;通…

.net服務器Kestrel配置Nginx作為反向代理

.NET服務器Kestrel配置Nginx作為反向代理 在ASP.NET Core應用程序的部署過程中&#xff0c;Kestrel是一款輕量級的跨平臺Web服務器。不過&#xff0c;直接將其暴露在互聯網上并非明智之舉。為了增強安全性、提升性能以及提高可伸縮性&#xff0c;我們可以借助Nginx作為反向代理…

MyBatis 在執行 SQL 時找不到名為 name 的參數

MyBatis 在執行 SQL 時找不到名為 name 的參數&#xff0c;因為當接口方法有多個參數時&#xff0c;沒有使用 Param(“name”) 明確指定參數名。 其他人說只有springboot1.x的版本才會出現該問題&#xff0c;但是我在使用2.x的版本時也出現了該問題Not found 參數 于是便回根溯…

【Git】git的回退功能

Git 的回退功能非常強大&#xff0c;但因為有多個命令&#xff0c;初學者很容易混淆。我們來系統地梳理一下最核心的幾個“回退”指令&#xff1a;git reset、git revert 和 git restore。 我會按照使用場景和安全級別來為你講解。核心區別&#xff1a;reset vs revert 這是最重…

STM32新建工程

1、新建工程 Keil5中&#xff0c;新建Project&#xff0c;選擇STM32Project文件夾&#xff0c;在此文件夾下新建一個文件夾“STM32工程模板”&#xff0c;然后給工程文件起名字“Project”選擇器件型號 2、添加啟動文件 新建start文件夾復制啟動文件&#xff1a;固件庫文件夾……

網絡傳輸過程

https傳輸過程客戶端發起HTTPS請求操作&#xff1a;用戶在瀏覽器輸入 https://www.example.com 技術細節&#xff1a; 客戶端向服務器443端口發起TCP連接 發送Client Hello消息&#xff08;包含支持的TLS版本、加密套件、客戶端隨機數&#xff09; 安全意義&#xff1a;建立安全…

【LeetCode 3440. 重新安排會議得到最多空余時間 II】解析

目錄LeetCode中國站原文原始題目題目描述示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;示例4&#xff1a;講解1. 新規則&#xff0c;新挑戰2. 收益從何而來&#xff1f;兩種可能性的誕生3. 我們的終極策略4. 當策略被壓縮到極致第一次遍歷&#xff1a;從左到右&#xf…

C++卸載了會影響電腦正常使用嗎?解析C++運行庫的作用與卸載后果

卸載C運行庫可能導致常用軟件癱瘓&#xff01;這些不起眼的組件為Photoshop、游戲等提供關鍵支持&#xff0c;多個版本共存是正常現象&#xff0c;隨意清理會引發程序報錯甚至閃退。一、前言&#xff1a;C不是“編程語言”那么簡單很多用戶在電腦中看到“Microsoft Visual C Re…

前端vue對接海康攝像頭流程

1、拆包攝像頭、插電源2、下載SADP&#xff08;設備網絡搜索&#xff09;&#xff0c;連接設備&#xff0c;獲取ip地址 下載地址&#xff1a;https://partners.hikvision.com/tools 找到自己的設備類型DS開頭3、攝像頭鏈接wifi、網線 登錄設備預覽配置網頁-配置網絡-可預覽等 4…