對象的繼承、命名空間、對象屬性枚舉
繼承
-
傳統形式:原型鏈的模式。缺點:沒用的屬性和方法都繼承下來。
-
借用構造函數:不能繼承構造函數的原型。並且需要執行一次構造函數。
-
共享原型:一個構造函數的原型設置成想要繼承的構造函數的原型。這樣就實現了繼承,但這不能隨便改動自己的原型。
-
聖盃模式:完善共享原型模式,中間添加個對象。
<script type = "text/javascript">
//聖盃模式實現繼承
Father.prototype.lastName = "lin";
function Father(){};
function Son(){};
function inherit(Target, Origin){
//Target.prototype = Origin.prototype;
function F(){};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
inherit(Son,Father);
var son = new Son();
console.log(son.__proto__);
</script>
命名空間
爲了不讓全局變量混淆,採用了定義一個全局對象,全局對象裏包含多個對象,這些對象中存儲每個功能的變量,這樣就能區分開各功能模塊的變量。這是個比較早期採用的方法。還可採用閉包的模式開發。
<script type = "text/javascript">
var org ={
department_one:{
zhangsan:{
name:"abc",
age:123
}
},
department_two:{
lisi:{
name:"efg",
age:345
}
}
}
var zs = org.department_one.zhangsan;
var ls = org.department_two.lisi;
console.log(zs.name);
console.log(ls.name);
//使用 with 操作命名空間中的變量。
with(org.department_one.zhangsan){
console.log(name);
}
with(org.department_two.lisi){
console.log(name);
}
</script>
實現鏈式調用
<script type = "text/javascript">
var person = {
smoke : function(){
console.log("Smoking....cool!");
return this;
},
drink : function(){
console.log("Drinking...cool too !");
return this;
},
perm : function(){
console.log("Perming...cool cool cool !");
return this;
}
}
person.drink().perm().smoke().drink().smoke().perm().perm().smoke().smoke().drink().smoke();
</script>
對象屬性的訪問方式
person.card1 和 person[‘card1’] 都是訪問 person 對象的 card1 屬性。
引擎會把 person.card1 轉成 person[‘card1’] 來訪問屬性。
<script type = "text/javascript">
var person = {
card1:{name:"中國銀行"},
card2:{name:"中國工商銀行"},
card3:{name:"中國建設銀行"},
card4:{name:"中國交通銀行"},
card5:{name:"匯豐銀行"},
card6:{name:"華夏銀行"},
card7:{name:"渤海銀行"},
card8:{name:"網商銀行"},
card9:function(){
console.log("花唄");
},
__proto__:{number:"6200000000000"}
}
Object.prototype.abc = "123";
console.log(person.card1);
console.log(person.card7);
for (const key in person) {
//是否對象本身的屬性,而不是繼承來的。
console.log(person.hasOwnProperty(key));
if(typeof(person[key]) == "function"){
person[key]();
}
else{
console.log(person[key]);
}
}
// in 操作符。對象 person 是否有card1 屬性,包括原型鏈。
console.log('card1' in person);
function Demo(){}
var demo = new Demo();
// instanceof 操作符。對象 demo 的原型鏈上是否有 Demo 原型。
console.log(demo instanceof Demo);
console.log(demo instanceof Object);
console.log([] instanceof Array);
console.log([] instanceof Object);
console.log(1 instanceof Object);
console.log("abc" instanceof Object);
</script>
對象的深度複製
<script type = "text/javascript">
var person = {
card1:{name:"中國銀行"},
card2:{name:"中國工商銀行"},
card1Name:function(){
return this.card1.name
},
cards:["中國銀行","中國工商銀行"],
card2Name:null
}
console.log(person.card2Name != null);
function clone(obj1,obj2){
obj2 = obj2 || {};
for (const key in obj1) {
if(obj1.hasOwnProperty(key)){
if(typeof(person[key]) == "object" && person[key] != null){
obj2[key] = (new Object().toString.call(person[key]) == "[object Array]") ? [] : {};
clone(obj1[key],obj2[key]);
}else{
obj2[key] = obj1[key];
}
}
}
return obj2;
}
var obj = {}
var obj0 = clone(person,obj);
console.log('obj.card1.name = ',obj.card1.name,'person.card1.name = ',person.card1.name);//修改前與person相同。
obj.card1.name = "消除";//修改obj。
console.log('obj.card1.name = ',obj.card1.name,'person.card1.name = ',person.card1.name);//修改obj後。
console.log('obj.card1Name() = ',obj.card1Name(),'person.card1Name() = ' ,person.card1Name());//修改obj後。
console.log('obj.cards = ',obj.cards,'person.cards = ' ,person.cards);
console.log('person object = ',person);
console.log('obj object = ',obj);
console.log('obj0 object = ',obj0,obj0===obj);
</script>
練習題:
console 輸出結果是什麼?
<script type = "text/javascript">
var f = (
function f(){
return "1";
},
function g(){
return 1;
}
)();
console.log(typeof(f));
</script>
<script type = "text/javascript">
var x = 1;
if(function f(){}){
//(function f(){}) 這個表達式判斷完就銷燬了。
x += typeof f;//此時 f 沒有定義 undefined
}
console.log(x);
</script>
<script type = "text/javascript">
console.log(undefined == null);
console.log(undefined === null);
console.log(undefined == undefined);
console.log(null == null);
console.log(undefined === undefined);
console.log(null === null);
console.log(undefined == NaN);
console.log(null == NaN);
console.log(null === NaN);
console.log(undefined === NaN);
console.log(NaN === NaN);
console.log(isNaN(100));
console.log(parseInt("1a")==1);
function myIsNaN(num){
var ret = Number(num);
ret += "";
if(ret == "NaN"){
return true;
}else{
return false;
}
}
console.log(myIsNaN("123"));
console.log({} == {});
console.log([] == []);
</script>
this 指針
-
函數預編譯過程 this --> window。
-
全局作用域裏 this --> window。
-
call/apply 可以改變函數運行時 this 指向。
-
obj.func();func()裏面的this指向obj。
this指針指向調用函數的對象,new 構造函數時使用閉包的特性產生新對象。
練習題
寫出輸出結果:
<script type = "text/javascript">
//控制檯輸出結果是:?????????
var name = "222";
var a = {
name : "111",
say : function(){
console.log(this.name);
}
}
var fun = a.say;
fun();
a.say();
var b = {
name : "333",
say : function(fun){
fun();
}
}
b.say(a.say);
b.say = a.say;
b.say();
</script>
<script type = "text/javascript">
var a = 5;
function Test(){
// new 的時候系統添加 this 局部變量。
// this = {
// __proto__:test.prototype
// }
a = 0;
console.log(a);//先找到局部變量 a ,輸出。
console.log(this.a);//找調用者裏變量 a , 輸出。
var a;
console.log(a);//先找到局部變量 a , 輸出。
}
Test(); // 0,5,0
new Test();// 0,undefined,0
</script>
<script type = "text/javascript">
function print(){
var marty = {
name : "marty",
printName : function(){console.log(this.name);}
}
var test1 = {name : "test1"};
var test2 = {name : "test2"};
var test3 = {name : "test3"};
test3.printName = marty.printName;
var printName2 = marty.printName.bind({name : 123});
//bind方法作用是給函數 printName 設置 this 指向定義的{name:123}對象。
marty.printName.call(test1);
marty.printName.apply(test2);
marty.printName();
printName2();
test3.pringName();
}
print();
</script>
<script type = "text/javascript">
var bar = {a:"002"};
function print(){
bar.a = 'a';
Object.prototype.b = 'b';
return function inner(){
console.log(bar.a);
console.log(bar.b);
}
}
print()();
</script>
marty.printName();
printName2();
test3.pringName();
}
print();
</script>
<script type = "text/javascript">
var bar = {a:"002"};
function print(){
bar.a = 'a';
Object.prototype.b = 'b';
return function inner(){
console.log(bar.a);
console.log(bar.b);
}
}
print()();
</script>