JavaScript入門【3】面向對象

1.對象:

1.概述:

   在js中除了5中基本類型之外,剩下得都是對象Object類型(引用類型),他們的頂級父類是Object;

2.形式:

   在js中,對象類型的格式為key-value形式,key表示屬性,value表示屬性的值

3.創建對象的方式:

方式1:通過new關鍵字創建(不常用)
    let person = new Object();// 添加屬性  與 值person.name="張三";person.age = 22;console.log(person)      

方式2:通過{}類似于JSON字符串的形式創建:
     let person = {name: '張三',age: 20}console.log(person);   

4.對象的相關操作:

1.添加屬性:
    let person = new Object();// 添加屬性  與 值person.name="張三";person.age = 22;console.log(person)      

let person = {name: '張三',age: 20}console.log(person);// 添加屬性person.sex = '男';

2.獲取屬性值:

對于new方式創建的對象,獲取屬性值的方式如下:

    let person = new Object();// 添加屬性  與 值person.name="張三";person.age = 22;console.log(person.name)       

對于{}方式創建的對象,獲取屬性值得方式如下(上面得方式也適用):

let person = {name: '張三',age: 20}console.log(person['age']);

3.刪除屬性:通過delete關鍵字實現(兩種創建方式都適用)
let person = {name: '張三',age: 20,sex:'男'}delete person.sex;console.log(person);

4.遍歷對象屬性:for-in循環
let person = {name: '張三',age: 20,sex:'男'}for (let personKey in person) {console.log(personKey,person[personKey]);}

2.函數:不依賴于實例對象

1.概述:

是由一連串的子程序(語句的集合)組成的,可以被 外部調用,向函數內部傳入參數之后,函數可以返回的一定的值得代碼集合;

2.函數對象的創建:

方式1;通過new關鍵字:(不常用)
let  函數名=new Function("執行的語句");
let funA = new Function("console.log('函數對象執行了')");
//調用函數:
funA();

方式2:聲明式創建函數
function 函數名(形參1,形參2.....) {語句}
function sum(num1, num2, num3) {console.log("執行了sum函數:收到了參數:", num1, num2, num3)//可以使用return 返回結果return num1 + num2;}//調用函數let ret=sum(1,2);console.log(ret);

注意事項:

  •   調用有參函數時,傳入的參數不受函數定義的函數列表影響,可以多傳,少穿,或者不傳;
    
  •   創建函數時,不涉及返回值(類似于Java中的構造方法),但函數體內可以return執行結果;
    

3.函數的類型:

1.常規函數:上述函數即為常規函數
function 函數名(形參1,形參2.....) {語句}   
2.匿名函數:沒有函數名,而是由一個變量進行接收
 let 變量名(函數名)=function(形參1,形參2.....) {執行語句}
3.嵌套函數:即函數體內包含一個子函數
 function 父函數名(形參1,形參2.....) {function 子函數名(形參1,形參2.....) {語句}   }   

注意:直接調用父函數時,無法執行子函數

function fu() {function zi() {console.log("我是子函數");}父函數的其他執行語句}   //調用父函數fu();

如果需要執行子函數,則需要在父函數中手動調用子函數

function fu() {function zi() {console.log("我是子函數");}zi();// 父函數的其他執行語句}   //調用父函數fu();

4.立即執行函數:可理解為函數一創建出來就被調用執行
(function (形參1,.....) {執行語句})(實參.........)
(function (msg) {console.log("我是一個匿名函數",msg)})('我是一段消息');

3.方法:需依賴于示例對象

1.方法的定義:

      需要先創建對象,然后依賴對象在創建方法;
 let person = {name:'張三',age:23,//定義方法sayHello:function () {console.log(this.name+",Hello")}}console.log(person)//調用方法person.sayHello();     

2.this關鍵字:

1.this出現在函數中:被直接調用,則this表示window對象
 <script>function fun() {console.log(this.constructor+ ",Hello")}fun();</script>      

通過輸出的構造方法名,可以看出此時的this表示window對象

2.this出現在方法中:this表示當前對象(誰調用,this就指代誰)
  function fun() {console.log(this.name + ",Hello")}let person = {name: '張三',age: 23,sayHello: fun}let person2 = {name: '李四',age: 23,sayHello: fun}person.sayHello(); //對象調用方法person2.sayHello();

通過測試結果可以看出,在方法中的this被那個對象調用,this就指代那個對象

4.創建對象的幾種方式:

1.直接創建:

存在問題:
       如果需要創建的對象過多,直接創建無法實現代碼的高復用性,代碼冗余嚴重;

2.通過工廠模式,封裝創建對象的方法:

實現:
 function createPerson(name, age) {let obj = new Object();obj.name = name;obj.age = age;obj.sayHello = function () {console.log(this.name)}return obj;}let person1 = createPerson('張三', 22); //Object 類型let person2 = createPerson('李四', 22); //Object 類型console.log(person1,person2)

存在問題:
通過下面測試結果可以看出,使用工廠模式創建的對象沒有獨立的類型,全部都是Object;
 function createPerson(name, age) {let obj = new Object();obj.name = name;obj.age = age;obj.sayHello = function () {console.log(this.name)}return obj;}let person1 = createPerson('張三', 22); //Object 類型let person2 = createPerson('李四', 22); //Object 類型console.log(typeof person1, typeof person2)

3.通過構造函數創建對象:

構造函數是什么:
  •    構造函數就是一個普通的函數,創建方式和普通函數沒有區別;
    
  •    不同的是 構造函數一般首字母大寫,調用時不同 需要使用new關鍵字;
    
構造函數的執行流程:
  •  1.調用構造函數,會立刻創建一個新的對象
    
  •  2.將新建的對象設置為函數中的this,在構造函數中可以使用this開引用新建的對象
    
  •  3.逐行執行函數中的代碼
    
  •  4.將新建的對象返回
    
實現通過構造函數創建對象:
  function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}let person1 = new Person('張三', 23);let person2 = new Person('李四', 23);console.log(person1, person2)

說明:

通過此種方式創建的對象,都有獨立的類型,不再是object,而是與構造函數有關

  function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}let person1 = new Person('張三', 23);let person2 = new Person('李四', 23);console.log(person1, person2) function Person2(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}let person3 = new Person2('李四', 23); //  判斷 person3 是 Person2 / Person 創建的console.log(person3 instanceof Person)console.log(person2 instanceof Person)console.log(person3 instanceof Person2)

由于person3是通過Person2構造函數創建的,所以 console.log(person3 instanceof Person)輸出為false,console.log(person3 instanceof Person2)輸出為true;

5.原型:

1.概述:

  •    我們創建的每一個函數,解析器都會向函數中添加一個屬性prototype,這個屬性對應著一個對象,這個對象就是我們所謂的原型對象,即顯式原型,
    
  •    原型對象就相當于一個公共的區域,所有同一個類的實例都可以訪問到這個原型對象,我們可以將對象中共有的內容,統一設置到原型對象中。
    
  •    普通函數調用prototype沒有任何作用,當函數以構造函數的形式調用時,它所創建的對象中都會有一個隱含的屬性,指向該構造函數的原型對象,我們可以通過__proto__(隱式原型)來訪問該屬性。
    

2.案例解析:

  //創建構造函數function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}//將屬性 或者 函數 存在原型中  共享的Person.prototype.xxx = "我是測試數據";Person.prototype.showInfo = function () {console.log(this.name, "我是原型中的方法")} let person1 = new Person('張三', 23);let person2 = new Person('李四', 23);console.log(person1, person2);

    //創建構造函數function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}//將屬性 或者 函數 存在原型中  共享的Person.prototype.xxx = "我是測試數據";Person.prototype.showInfo = function () {console.log(this.name, "我是原型中的方法")} let person1 = new Person('張三', 23);let person2 = new Person('李四', 23);//person1 訪問xxx 先從person1對象自身尋找xxx屬性//沒有的 就去原型中找// 在沒有  就通過父類找console.log(person1.xxx, person2.xxx)person2.showInfo();
          ![](https://cdn.nlark.com/yuque/0/2024/png/45532635/1731664800063-21502bd1-ec70-43a7-8239-67f169e58805.png)

因為在Person類的原型對象中添加了屬性xxx和showinfo方法,而person1和person2作為它的實例對象,在訪問時,由于從自身無法獲取到,就向上在共享的原型對象中訪問到了屬性xxx和方法showinfo;

  //創建構造函數function Person(name, age) {this.name = name;this.age = age;this.sayName = function () {console.log(this.name)}}//將屬性 或者 函數 存在原型中  共享的Person.prototype.xxx = "我是測試數據";Person.prototype.showInfo = function () {console.log(this.name, "我是原型中的方法")} let person1 = new Person('張三', 23);let person2 = new Person('李四', 23);//使用 in 檢查對象中是否 含有某個屬性  有  true 沒有 falseconsole.log('name' in person1);console.log('xxx' in person1);console.log(person1.hasOwnProperty('name'))//true  xxx不是person1 自身的數據console.log(person1.hasOwnProperty('xxx'))console.log(person1.__proto__.hasOwnProperty('xxx'))

由于xxx屬性是原型對象中的屬性,而不是person1自身的屬性,所以測試結果為false;

6.繼承:

1.方式:

  • ** * 1.原型鏈繼承**
    
  • **     * 2.構造方法繼承**
    
  • **     * 3.組合繼承**
    
  • **     * 4.原型式繼承**
    
  • **     * 5.寄生繼承**
    
  • **     * 6.寄生組合繼承**
    

2.原型鏈繼承:

實現:

 function SupperType() {this.supProp = "我是父類型中的屬性"}//給父類的原型添加方法SupperType.prototype.showSupperProp = function () {console.log(this.supProp);}//創建子類原型function SubType() {this.subType = "我是子類的屬性"}//繼承  讓子類的原型屬性 指向 父類類型SubType.prototype = new SupperType();//將子類的原型的構造方法屬性設置為子類自己SubType.prototype.constructor = SubType;//子類的原型對象添加方法SubType.prototype.showSubProp = function () {console.log(this.subType)}let subType = new SubType();//調用父類的原型中的方法subType.showSupperProp();//調用子類自己的原型中的方法subType.showSubProp();//獲取父類中的屬性console.log(subType.supProp)console.log(subType)

說明:

 上述代碼中是通過將子類的原型對象指向父類對象來實現的,在子類訪問父類屬性或方法時,先在自身找,如果找不到,再在子類的原型對象中找,要是還找不到,就在父類對象中找,父類對象屬性中也沒有,就在父類的原型對象中找,就這樣以引用鏈的形式查找,進而實現了繼承;

存在問題:

  •    1.不能為父類傳參;
    
  •    2.原型鏈繼承多個實例的引用類型屬性,且由于指向是相同的,一個實例修改了原型屬性,另一個實例的原型屬性也會被影響;
    

3.構造函數繼承:

實現:

  //1.定義父類的構造函數function SupperType(name) {this.name = name;this.showSupperName = function (){console.log(this.name,"這是方法")}}SupperType.prototype.xxx= "父類原型屬性";//2.創建子類構造函數function SubType(name,age) {//在子類中 調用call 繼承父類中的屬性與方法SupperType.call(this,name);this.age = age;}SubType.prototype.showInfo = function () {console.log(this.name,this.age)}let subType = new SubType('張三',20);subType.showSupperName();//子類原型中的方法subType.showInfo();//通過子類實例 調用父類原型中的屬性console.log(subType.xxx);console.log(subType)

說明:

通過此方式實現繼承與原型鏈的方式不同,此方式更像是把父類的屬性和方法復制到子類中,雖然最后看似在調用父類的屬性和方法,但其實是調用本類的屬性和方法,因此通過此方式并沒有建立完全的繼承關系,所以subType的父類是Object,而非SupperType,因此子類SubType是無法訪問到父類SupperType的原型對象中的屬性和方法的;

存在問題:

 通過構造函數實現繼承關系,解決了原型鏈繼承的問題.但又出現了下面的新問題:
  •   無法訪問父類原型對象中的方法或屬性;
    

4.組合繼承:

實現:

<script>//1.定義父類的構造函數function SupperType(name) {this.name = name;this.showSupperName = function (){console.log(this.name,"這是父類方法")}}SupperType.prototype.xxx= "父類原型屬性";//2.創建子類構造函數function SubType(name,age) {//在子類中 調用call 繼承父類中的屬性與方法SupperType.call(this,name);this.age = age;}SubType.prototype=Object.create(new SupperType());SubType.prototype.constructor=SubType;SubType.prototype.showinfo=function(){console.log(this.name,this.age,"子類方法")}let sub=new SubType("張三",22);sub.showSupperName();sub.showinfo();console.log(sub.xxx);console.log(sub);
</script>   

說明:

此方式結合了引用鏈繼承和構造方法繼承的特點,解決了它們自身存在的問題

存在問題:

雖然組合繼承解決了引用鏈繼承和構造方法繼承所存在的問題,但有出現了新的問題;

  • 父類中的實例屬性和方法在子類實例中又在子類原型中,內存開銷變大;
    

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

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

相關文章

oracle主備切換參考

主備正常切換操作參考&#xff1a;RAC兩節點->單機 &#xff08;rac和單機的操作區別&#xff1a;就是關閉其它節點&#xff0c;剩一個節點操作即可&#xff09; 1.主庫準備 檢查狀態 SQL> select inst_id,database_role,OPEN_MODE from gv$database; INST_ID DATA…

端到端自動駕駛系統實戰指南:從Comma.ai架構到PyTorch部署

引言&#xff1a;端到端自動駕駛的技術革命 在自動駕駛技術演進歷程中&#xff0c;端到端&#xff08;End-to-End&#xff09;架構正引領新一輪技術革命。不同于傳統分模塊處理感知、規劃、控制的方案&#xff0c;端到端系統通過深度神經網絡直接建立傳感器原始數據到車輛控制…

使用 Kotlin 和 Jetpack Compose 開發 Wear OS 應用的完整指南

環境配置與項目搭建 1. Gradle 依賴配置 // build.gradle (Module) android {buildFeatures {compose true}composeOptions {kotlinCompilerExtensionVersion "1.5.3"} }dependencies {def wear_compose_version "1.2.0"implementation "androidx.…

應用層協議簡介:以 HTTP 和 MQTT 為例

文章目錄 應用層協議簡介&#xff1a;什么是應用層協議&#xff1f;為什么需要應用層協議&#xff1f;什么是應用層協議&#xff1f;為什么需要應用層協議&#xff1f; HTTP 協議詳解HTTP 協議特點HTTP 工作的基本原理HTTP 請求與響應示例為什么 Web 應用基于 HTTP 請求&#x…

Kafka快速安裝與使用

引言 這篇文章是一篇Ubuntu(Linux)環境下的Kafka安裝與使用教程&#xff0c;通過本文&#xff0c;你可以非常快速搭建一個kafka的小單元進行日常開發與調測。 安裝步驟 下載與解壓安裝 首先我們需要下載一下Kafka&#xff0c;這里筆者采用wget指令&#xff1a; wget https:…

PD 分離推理的加速大招,百度智能云網絡基礎設施和通信組件的優化實踐

為了適應 PD 分離式推理部署架構&#xff0c;百度智能云從物理網絡層面的「4us 端到端低時延」HPN 集群建設&#xff0c;到網絡流量層面的設備配置和管理&#xff0c;再到通信組件和算子層面的優化&#xff0c;顯著提升了上層推理服務的整體性能。 百度智能云在大規模 PD 分離…

flutter Stream 有哪兩種訂閱模式。

Flutter 中的 Stream 有兩種訂閱模式&#xff1a; ?單訂閱模式 (Single Subscription)?? 只能有一個訂閱者&#xff08;listen 只能調用一次&#xff09;&#xff0c;后續調用會拋出異常。數據僅在訂閱后開始傳遞&#xff0c;適用于點對點通信場景&#xff08;如文件讀取流…

Python爬蟲實戰:研究JavaScript 環境補全逆向解密

1. 引言 1.1 研究背景與意義 隨著互聯網的快速發展,大量有價值的數據被發布在各種網站上。然而,為了保護數據安全和商業利益,許多網站采用了 JavaScript 加密技術對敏感數據進行保護。這些加密技術使得傳統的爬蟲技術難以直接獲取和解析數據,給數據采集工作帶來了巨大挑戰…

[system-design] ByteByteGo_Note Summary

目錄 通信協議 REST API 與 GraphQL gRPC 如何工作&#xff1f; 什么是Webhook&#xff1f; 如何提高應用程序接口的性能&#xff1f; HTTP 1.0 -> HTTP 1.1 -> HTTP 2.0 -> HTTP 3.0 (QUIC) SOAP vs REST vs GraphQL vs RPC 代碼優先與應用程序接口優先 HTT…

Linux中的進程

進程控制 fork 函數 fork 函數從已存在的進程中創建新的進程&#xff0c;已存在進程為父進程&#xff0c;新創建進程為子進程 fork 的常規用法 一個父進程希望復制自己&#xff0c;使父子進程同時執行不同的代碼段。例如&#xff0c;父進程等待客戶端請求&#xff0c;生成子…

EDR與XDR如何選擇適合您的網絡安全解決方案

1. 什么是EDR&#xff1f; 端點檢測與響應&#xff08;EDR&#xff09; 專注于保護端點設備&#xff08;如電腦、服務器、移動設備&#xff09;。通過在端點安裝代理軟件&#xff0c;EDR實時監控設備活動&#xff0c;檢測威脅并快速響應。 EDR核心功能 實時監控&#xff1a;…

AGI大模型(21):混合檢索之混合搜索

為了執行混合搜索,我們結合了 BM25 和密集檢索的結果。每種方法的分數均經過標準化和加權以獲得最佳總體結果 1 代碼 先編寫 BM25搜索的代碼,再編寫密集檢索的代碼,最后進行混合。 from rank_bm25 import BM25Okapi from nltk.tokenize import word_tokenize import jieb…

2025最新的軟件測試面試大全(含答案+文檔)

一、軟件測試基礎面試題 1、闡述軟件生命周期都有哪些階段? 常見的軟件生命周期模型有哪些? 軟件生命周期是指一個計算機軟件從功能確定設計&#xff0c;到開發成功投入使用&#xff0c;并在使用中不斷地修改、增補和完善&#xff0c;直到停止該軟件的使用的全過程(從醞釀到…

C++.神經網絡與深度學習(二次修改)

神經網絡與深度學習 1. 神經網絡基礎1.1 神經元模型與激活函數1.2 神經網絡結構與前向傳播2.1 損失函數與優化算法均方誤差損失函數交叉熵損失函數梯度下降優化算法2.2 反向傳播與梯度計算神經元的反向傳播3.1 神經元類設計與實現神經元類代碼實現代碼思路3.2 神經網絡類構建神…

FPGA圖像處理(六)------ 圖像腐蝕and圖像膨脹

默認迭代次數為1&#xff0c;只進行一次腐蝕、膨脹 一、圖像腐蝕 1.相關定義 2.圖像腐蝕效果圖 3.fpga實現 彩色圖像灰度化&#xff0c;灰度圖像二值化&#xff0c;圖像緩存生成濾波模塊&#xff08;3*3&#xff09;&#xff0c;圖像腐蝕算法 timescale 1ns / 1ps // // Des…

中國版Cursor:CodeBuddy騰訊云代碼助手使用體驗

我正在參加CodeBuddy「首席試玩官」內容創作大賽&#xff0c;本文所使用的 CodeBuddy 免費下載鏈接&#xff1a;騰訊云代碼助手 CodeBuddy - AI 時代的智能編程伙伴” 1.CodeBuddy簡介 騰訊云代碼助手CodeBuddy&#xff0c;這個是一款編程插件&#xff0c;我們可以在各個編程…

Go語言 GORM框架 使用指南

在 Go 語言社區中&#xff0c;數據庫交互一直是開發者們關注的重點領域&#xff0c;不同開發者基于自身的需求和偏好&#xff0c;形成了兩種主要的技術選型流派。一部分開發者鐘情于像sqlx這類簡潔的庫&#xff0c;盡管其功能并非一應俱全&#xff0c;但它賦予開發者對 SQL 語句…

從零開始學習three.js(18):一文詳解three.js中的著色器Shader

在WebGL和Three.js的3D圖形渲染中&#xff0c;著色器&#xff08;Shader&#xff09; 是實現復雜視覺效果的核心工具。通過編寫自定義的著色器代碼&#xff0c;開發者可以直接操作GPU&#xff0c;實現從基礎顏色渲染到動態光照、粒子效果等高級圖形技術。本文將深入解析Three.j…

Python函數庫調用實戰:以數據分析為例

一、引言 Python之所以在編程領域廣受歡迎&#xff0c;很大程度上得益于其豐富且強大的函數庫。這些函數庫涵蓋了從數據分析、科學計算到Web開發、機器學習等眾多領域&#xff0c;極大地提高了開發效率。本文將以數據分析為例&#xff0c;介紹如何調用Python的一些常用函數庫。…

shell腳本之條件判斷,循環控制,exit詳解

if條件語句的語法及案例 一、基本語法結構 1. 單條件判斷 if [ 條件 ]; then命令1命令2... fi2. 雙分支&#xff08;if-else&#xff09; if [ 條件 ]; then條件為真時執行的命令 else條件為假時執行的命令 fi3. 多分支&#xff08;if-elif-else&#xff09; if [ 條件1 ]…