JS對象的概念、聲明方式等及js中的繼承與封裝

来源:https://www.cnblogs.com/chenyingying0/archive/2020/02/14/12305709.html
-Advertisement-
Play Games

對象的遍歷 對象可以當做數組處理,使用for in var person={}; person.name="cyy"; person.age=25; person.infos=function(){ alert(this.name+" "+this.age); } for(var i in pers ...


對象的遍歷

對象可以當做數組處理,使用for in

var person={};
person.name="cyy";
person.age=25;
person.infos=function(){
    alert(this.name+" "+this.age);
}

for(var i in person){
    console.log(i);//屬性名或方法名
    console.log(person[i]);//屬性值或方法值
}

 

 使用構造函數聲明的對象,需要實例化之後再進行遍歷

function Person(){
    this.name="cyy";
    this.age=25;
}
var p=new Person();
for(var i in p){
    console.log(i+":"+p[i]);
}

對象在記憶體中的分佈

參考以下神圖

 

 

 封裝:把對象的內部數據和操作細節進行隱藏

提供private關鍵詞隱藏某些屬性和方法,限制被封裝的數據或者內容的訪問,只對外提供一個對象的專門訪問的介面

介面一般為調用方法

不過js沒有提供這樣的關鍵詞,但可以通過閉包來實現

函數內部聲明的變數,外部是訪問不到的

function fn(){
    var n=1;
    function fn2(){//特權方法
        alert(++n);
    }
    return fn2;
}
fn()();//2
//封裝
function Person(){
    var name="cyy";
    function _name(){
        alert(name);
    }
    this.name=function(){//這是給外部的介面
        return _name;
    }
}
var p=new Person();
var fn=p.name();
fn();//cyy

封裝的缺點:1、占用記憶體   2、不利於繼承


 

利用閉包特性來封裝一個對象student,運用對象student存儲一個學生的信息,信息包括姓名,性別和年齡,這些信息不可被外部直接訪問,只能通過對象的方法獲取 

student的數據結構如下:

 

 

//封裝
function Student(){
    var obj={};
    function _set(name,sex,age){
        obj.name=name;
        obj.sex=sex;
        obj.age=age;
    }
    function _get(){
        return obj.name+" "+obj.sex+" "+obj.age;
    }
    obj.get=function(){//對外介面
        return _get;
    }
    obj.set=function(){//對外介面
        return _set;
    }
    return obj;
}
var stu=new Student;
stu.set()("小明", "男", 23);
console.log(stu.get()());//小明 男 23

原型和原型鏈

原型:利用 prototype 添加屬性和方法,prototype對象

原型鏈:JS在創建對象時,有一個 __proto__ 的內置屬性,指向它的原型對象 prototype

var Person=function(){}
var p=new Person();
Person.prototype.say=function(){
    alert("老娘超美");
}
p.say();
/*
p沒有say方法,所以會去p.__proto__里找
p.__proto__是一個對象,指向Person.prototype
Person.prototype中有say方法
 */


/*
創建對象的過程
1、創建對象 var p={}
2、將Person的原型對象賦值給p  p.__proto__=Person.prototype
3、初始化對象p  Person.call(p)
 */
alert(p.__proto__==Person.prototype);//true

原型和原型鏈,實現原型繼承

var Person=function(){}//Person是一個對象
Person.prototype.say=function(){
    alert("陳鶯鶯超美");
}
var Cyy=function(){};//Cyy也是一個對象
Cyy.prototype=new Person();//將Cyy的原型指向Person,實現Cyy繼承自Person
Cyy.prototype.sing=function(){
    alert("陳鶯鶯會唱歌");
}

var me=new Cyy();
me.say();//陳鶯鶯超美
me.sing();// 陳鶯鶯會唱歌

/*
分析:me.__proto__  ->  Cyy.ptototype  -> Person.prototype
Person是父  Cyy是子
繼承:如果子類中沒有的,會繼承自父類;如果子類和父類中都有,那麼子類的會覆蓋掉父類的
 */

__proto__ 實現原型繼承

function Person(name,age){
    this.name=name;
    this.age=age;
}
Person.prototype.say=function(){
    alert(this.name+" "+this.age);
}

function Student(){};
Student.prototype=new Person("cyy",25);
//Person是Student的父類
//子類必須繼承自父類的實例
Student.prototype.grade=3;
Student.prototype.test=function(){
    alert(this.grade);
}

var s=new Student();
s.say();//cyy 25
s.test();//3
//s.__proto__ -> Student.prototype -> Person.prototype

原型的值可以是一個對象,也可以是null

原型鏈的最終指向null

alert(Object.prototype.__proto__);//null
// 情況一
function Parent(){
    this.name="parent";
    this.age=45;
}
function Child(){
    this.age=25;
}
Child.prototype.name="child";
Child.prototype=new Parent();
var c=new Child();
console.log(c.name);//parent

// 情況二
function Parent(){
    this.name="parent";
    this.age=45;
}
function Child(){
    this.age=25;
}
Child.prototype=new Parent();
Child.prototype.name="child";
var c=new Child();
console.log(c.name);//child

情況一中,Child.prototype=new Parent(); 這一句覆蓋掉了前面的 Child.prototype.name="child";

屬性的值與代碼執行順序有關,後繼承的父級的,會覆蓋住先定義的自己的


 

創建一個動物類的對象 ,對象中有動物名稱和數量的屬性 。創建一個貓的對象並繼承動物類對象 ,併為貓對象定義一個方法 。實例化一個貓對象 ,調用其方法 ,彈出動物名稱和數量

function Animal(name,number){
    this.name=name;
    this.number=number;
}
function Cat(){};
Cat.prototype=new Animal("cat",30);
Cat.prototype.info=function(){
    alert(this.name+" "+this.number);
}
var c=new Cat();
c.info();//cat 30

構造函數的繼承

在子類內部構造父類的對象來實現繼承

父對象被子對象繼承後,所有的屬性和方法,都會傳遞到子對象中

function Parent(name){
    this.name=name;
    this.pSay=function(){
        alert(this.name);
    }
}
function Child(name,age){
    this.obj=Parent;
    this.obj(name);//繼承了父元素中的兩句代碼
    this.age=age;
    this.cSay=function(){
        alert(this.name+" "+this.age);
    }
}
var p=new Parent("爸爸");
p.pSay();//爸爸
var c=new Child("女兒",25);
c.cSay();//女兒 25
c.pSay();//女兒

對象內置方法中的apply和call都可用於繼承,兩者的區別在於傳參方式不同

obj.call( 方法, var1, var2...)

obj.apply( 方法, [var1, var2...])

function Parent(name,age,sex){
    this.name=name;
    this.age=age;
    this.sex=sex;
    this.say=function(){
        alert(this.name+" "+this.age+" "+this.sex);
    }
}
function Child(name,age){
    //實現繼承
    Parent.call(this,name,age);//this是指Child
}
function Child2(name,age){
    //實現繼承
    Parent.apply(this,[name,age]);//this是指Child
}

var c=new Child("cyy",25);
c.say();
//cyy 25 undefined
//Child也擁有了Parent的屬性和方法
var c2=new Child2("cyy2",25);
c2.say();//cyy2 25 undefined

使用構造方法創建一個動物類對象Animal, 對象中定義屬性有動物名稱和數量 ,並且定義一個方法。再創建兩個動物的對象(如貓和狗),一個動物使用call方法實現繼承Animal, 一個動物使用apply方法實現繼承Animal。分別實例化兩個動物並彈出動物的名稱和數量

function Animal(name,num){
    this.name=name;
    this.num=num;
    this.getInfo=function(){
        alert(this.name+" "+this.num);
    }
}
function Cat(name,num){
    Animal.call(this,name,num);
}
function Dog(name,num){
    Animal.apply(this,[name,num]);
}
var c=new Cat("cat",20);
c.getInfo();//cat 20
var d=new Dog("dog",30);
d.getInfo();//dog 30

JS面向對象的關鍵詞

instanceof  變數是否是對象的實例

var arr=new Array();
console.log(arr instanceof Array);//true
console.log(arr instanceof Object);//true

function Person(){};
var p=new Person();
console.log(p instanceof Person);//true
console.log(p instanceof Object);//true

 

delete 刪除對象屬性(不能刪除原型鏈中的屬性和方法

function Person(){
    this.name="cyy";
    this.eat=function(){
        alert("吃飯");
    }
}
var p=new Person();
console.log(p.name);//cyy
delete p.name;//刪除對象的屬性
console.log(p.name);//undefined

p.eat();//吃飯
delete p.eat();//吃飯  刪除對象的方法,失敗
p.eat();//吃飯

var name="cyy";
console.log(name);//cyy
delete name;
console.log(name);//name is not defined

 

call 參數逐個實現繼承

apply 參數以數組方式實現繼承

function add(a,b){
    alert(a+b);
}
function sub(a,b){
    alert(a-b);
}
add.call(sub,4,8);
//12 調用的是add這個方法
add.call(sub2,4,8);
//sub2 is not defined 只能引用一個已經存在的對象

add.apply(sub,[3,2]);
function Animal(){
    this.name="animal";
    this.show=function(){
        alert(this.name);
    }
}
function Cat(){
    this.name="cat";
}
var a=new Animal();
var c=new Cat();
a.show.call(c);//cat c擁有了a所擁有的show方法
a.show.apply(c,[]);//cat c擁有了a所擁有的show方法

創建兩個數組 ,並運用apply實現兩個數組的拼接

var arr1=[2,3];
var arr2=[4,5];
arr1.push.apply(arr1,arr2);
//調用的是apply前面的方法:arr1.push
console.log(arr1);

 

arguments 實參的類數組對象

callee  返回正在執行的function對象,返回的是function的內容

arguments.callee

function fn(){
    console.log(arguments.callee);
    /*ƒ fn(){
        console.log(arguments.callee);
        }
    */
    //console.log(arguments.callee());不停調用自身,陷入死迴圈
}
fn();

 

常用於遞歸函數調用函數自身

var sum=function(n){
    if(n<=1) return 1;
    return n+sum(n-1);
}
console.log(sum(4));//10
var sum=function(n){
    if(n<=1) return 1;
    return n+arguments.callee(n-1);
}
console.log(sum(4));//10

 

this 指向當前對象

1、this函數調用

var x=1;
function fn(){
    this.x=2;//this改變的是全局變數的x的值
}
fn();
console.log(x);//2

2、this作為方法調用

構造函數內指代當前對象

function Person(){
    this.name="cyy";
    this.show=function(){
        alert(this.name);
    }
}
var p=new Person();
p.show();//cyy

3、在call和apply中,this作為第一個參數

var name="cyy";
function show(){
    alert(this.name);
}
var obj={};
obj.name="cyy2";
obj.showName=show;
obj.showName.apply();//調用show(),this指向全局
obj.showName.apply(window);//同上
obj.showName.apply(obj);//調用show(),this指向obj

用arguments計算參數總和

function sum(){
    var sum=0;
    for(var i=0;i<arguments.length;i++){
        sum+=arguments[i];
    }
    return sum;
}
console.log(sum(2,5,7));//14

對象冒充:將父類的屬性和方法傳給子類,作為特權屬性和特權方法

function Parent(name,age){
    this.name=name;//特權屬性
    this.age=age;
    this.show=function(){//特權方法
        alert(this.name+" "+this.age);
    }
}
Parent.prototype.walk=function(){//非特權方法
    alert("walking...");
}

function Child(name,age,sex){
    this.obj=Parent;//對象冒充,可以使用父類的特權屬性和特權方法
    this.obj(name,age);
    this.sex=sex;
}
var c=new Child("cyy",25,"女");
c.show();//cyy 25
c.walk();// c.walk is not a function

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 SQL 的哲學 形如 Linux 哲學一切都是文件,在 SQL 領域也有這樣一條至理名言 2 關係資料庫 所謂關係資料庫(Relational database)是創建在關係模型基礎上的資料庫,藉助於集合代數等數學概念和方法來處理資料庫中的數據。 現實世界中的各種實體以及實體之間的各種聯繫均用關 ...
  • 該文為《 MySQL 實戰 45 講》的學習筆記,感謝查看,如有錯誤,歡迎指正 一、索引簡介 索引就類似書本的目錄,作用就是方便我們更加快速的查找到想要的數據。 索引的實現方式比較多,常見的有 ,`有序數組 搜索樹`。 1.1 哈希表 是將數據以 的形式存儲起來,簡單來說就是將 通過哈希函數換算成數 ...
  • 資料庫索引是資料庫系統中一個重要的概念,索引也叫做 key ,是一種用於提升資料庫查詢效率的數據結構,我們可以把索引理解成一本書的目錄,通過目錄我們可以快速找到對應章節的內容,同樣的,通過資料庫索引,我們可以快速找到數據表中對應的記錄。 ...
  • 上一章聊到 TsFile 的文件組成,以及數據塊的詳細介紹。詳情請見: 時序資料庫 Apache-IoTDB 源碼解析之文件數據塊(四) 打一波廣告,歡迎大家訪問IoTDB 倉庫,求一波 Star。 這一章主要想聊聊: TsFile索引塊的組成 索引塊的查詢過程 索引塊目前在做的改進項 索引塊 索引 ...
  • 簡單介紹了線性佈局和相對佈局,同時分析了xml文件三個固定開頭xmlns:namespace-prefix="namespaceURI" ...
  • 在無序列表ul>li中,無線列表的標誌是出現在各列表前面的圓點。在有序列表ol>li中,前面預設帶有數字,如何修改列表前面的項目符號,只需要通過list-style調整就好,常見的符號有(/*內容註釋部分*/)list-style-type:circle;/*空心圓*/list-style:none... ...
  • 常見的color, font-family, background 等css屬性都能夠設置鏈接的樣式,a鏈接的特殊性在於能夠根據它們所處的狀態來設置它們的樣式。a標簽與人交互的4個狀態屬於偽類狀態切換,常見的鏈接四種狀態為:a:link - 普通的、未被訪問的鏈接a:visited - 用戶已訪問的... ...
  • CSS文本屬性可定義文本的外觀,這是毫無疑問的,其次css可以通過以下屬性改變文字的排版,比方說letter-spacing實現字元間距text-indent: 2em;完成首行縮進2字元word-spacing改變了文字的間距,direction改變文本從左至右的閱讀順序,white-space處... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...