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
  • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
  • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
  • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
  • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
  • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
  • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
  • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
  • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
  • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
  • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...