對象的繼承、命名空間、對象屬性枚舉

對象的繼承、命名空間、對象屬性枚舉

繼承

  1. 傳統形式:原型鏈的模式。缺點:沒用的屬性和方法都繼承下來。

  2. 借用構造函數:不能繼承構造函數的原型。並且需要執行一次構造函數。

  3. 共享原型:一個構造函數的原型設置成想要繼承的構造函數的原型。這樣就實現了繼承,但這不能隨便改動自己的原型。

  4. 聖盃模式:完善共享原型模式,中間添加個對象。

 <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 指針

  1. 函數預編譯過程 this --> window。

  2. 全局作用域裏 this --> window。

  3. call/apply 可以改變函數運行時 this 指向。

  4. 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>

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章