物件的遍歷
物件可以當做陣列處理,使用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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/149380.html
標籤:JavaScript
上一篇:04.JS邏輯結構
下一篇:nodejs下載網頁所有圖片
