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

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

對象的遍歷 對象可以當做數組處理,使用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

 


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

更多相關文章
  • 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處... ...
一周排行
  • Consul是HashiCorp公司推出的開源工具,Consul由Go語言開發,部署起來非常容易,只需要極少的可執行程式和配置文件,具有綠色、輕量級的特點。Consul是`分散式`的、`高可用`的、 `可橫向擴展`的用於實現分散式系統的服務發現與配置。 ...
  • Blazor的哪個特點, 可以讓程式員快速完成任務? 這隨筆講解的是使用代碼上下文來節約代碼, 讓驗證碼機制變得更加簡易. ...
  • 在C#中,struct和class都是用戶定義的數據類型,struct和class有許多不同之處,但主要的區別是: Class是引用類型,它保存在堆上並且能夠被垃圾回收;然而stuct是值類型,它保存在棧上或者內嵌在它的包含類型之中。因此,從總體上來說struct比class節省記憶體。 下圖是Cla ...
  • 這篇文章,我將帶領大家學習ASP.NET Core中的launchSettings.json文件。為了學習它,我們打開之前建的空白模板的ASP.NET Core項目。 從上面的圖片中你可以看到,我們項目的屬性中有一個launchSettings.json文件。那麼我們來一起學習這個重要的文件吧。la... ...
  • [TOC] 都是迭代,為啥我一定要用foreach ​ 問題起源於本人的一個練手的撲克牌程式:洗完牌之後要發給場上的三人。 ​ 只發給單個人的時候用 foreach 迴圈一下就好了,但三個人就有點麻煩了。 ​ 牌組用list保存你可能會想到這樣寫: 對於字典,可以使用 : 可能各位早會這樣弄了,讓各 ...
  • 首先以Winform項目開發舉例 1.完整的學習計劃 2.對於學習內容分類 3.良好的學習習慣 4.項目實踐 學習計劃 1.基礎篇 2.提高篇 3.應用篇 內容分類 1.語法 2.控制項 3.業務邏輯 學習習慣 1.時間安排 2.進度安排 3.記錄筆記 4.練習寫代碼 項目實踐 1.實現頁面展示 2. ...
  • 在進行 Asp.NetCore.MVC 文件上傳時,後臺無法正常讀取文件流保存,出現:Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead. 查找資料,發現需要 ...
  • 在這篇文章中,我將詳細介紹在ASP.NET Core中使用appsettings.json文件的重要性。這篇文章,我將詳細介紹下麵幾個問題:在ASP.NET Core應用程式中,有哪些不同的配置資源可用呢?什麼是ASP.NET Core appsetting.json文件?在ASP.NET Core ...
  • 這篇文章中,我將帶領大家一起詳細學習:ASP.NET Core Middleware Components.這篇文章中,我將詳細討論下麵幾個問題:什麼是ASP.NET Core 中的中間件組件?ASP.NET Core應用程式中,在哪裡來使用中間件組件?怎樣來配置ASP.NET Core 應用程式中... ...
  • 參考 ABP設計UI菜單欄的源碼分析,抽出了ABP這塊自定義擴展的實現。在ABP的源碼裡面有很多地方都用到了這種設計方式,實現了用戶自定義擴展。 新建一個空的asp.net core項目,新建一個類,源碼: StartUp類源碼: 擴展點:在 中提供用戶自定義擴展點,完美的是下瞭解耦。 參考: "B ...