JavaScript物件導向入門

Java3y發表於2018-03-01

什麼是JavaScript?

我們可以從幾個方面去說JavaScript是什麼:

  • 基於物件
    • javaScript中內建了許多物件供我們使用【String、Date、Array】等等
    • javaScript也允許我們自己自定義物件
  • 事件驅動
    • 當使用者觸發執行某些動作的時候【滑鼠單機、滑鼠移動】,javaScript提供了監聽這些事件的機制。當使用者觸發的時候,就執行我們自己寫的程式碼。
  • 解釋性語言
    • [x] javaScript程式碼是由瀏覽器解析的,並不需要編譯。
  • 基於瀏覽器的動態互動技術
    • 既然javaScript是由瀏覽器解析的,那麼它肯定要基於瀏覽器。 javaScript讓網頁變得更加“靈活""
  • 弱型別
    • [x] 像java、c++等編譯型語言,要先定義變數,後使用。javaScript能夠直接使用,不需要先定義

JavaScript變數型別

javaScript變數可分為三種型別:

  • 基本型別【number、string、boolean】
    • javaScript是弱型別語言,在執行的時候才知道具體的型別是什麼。所有型別都用var來修飾。
  • 特殊型別【null、undefined】
    • 當定義了變數,沒有任何賦值的時候,該變數就是undefined型別
  • 複合型別【陣列、物件、函式】

javaScript物件的型別

在JavaScript中物件的型別可分為4種:

  • 內建物件【String、Math、Array】
  • 自定義物件【程式設計師自己建立的物件】
  • 瀏覽器物件【windows、document、history、status等等與瀏覽器相關的物件】
  • ActiveXObject(XMLHttpRequest)物件【非同步物件,使用AJAX用到的物件,使用該物件與伺服器進行非同步互動】

定義函式三種方式

函式是屬於特殊型別的一種,在另外一篇博文已經講解了建立物件、建立類的幾種方式,可參考blog.csdn.net/hon_3y/arti…

值得注意的是:javaScript定義函式的時候,引數的型別是不用宣告的!

正常方式

下面就定義了一個名稱為mysum的函式

        function mysum(num1,num2){
			return num1 + num2;
		}
		var myresult = mysum(100,200);
		alert("myresult="+myresult);
複製程式碼

Function定義

在JavaScript中, 一切皆是物件,函式也可以用一個物件來代表:Function,我們可以使用Function來建立物件:

函式引數全都是字串,最後一個字串是方法體


		var youresult = new Function("num1","num2","return num1+num2");
		alert( youresult(1000,2000) );
複製程式碼

由於這種方法寫起來並不好些,可讀性也不太好,因此很少使用【不推薦使用】


匿名建立函式

其實這種和第一種差不多,只不過是將一個無名的函式賦值給一個變數。那麼這個變數就代表了這個函式。



var theyresult = function(num1,num2){
							return num1 + num2;	
						 }
		alert( theyresult(10000,20000) );

複製程式碼

theyresult這個變數就代表了函式。


建立物件

方式①

直接使用new Object()


  var obj = new Object();

複製程式碼

方式②

使用空的{}大括號

    var obj2 = {};
複製程式碼

測試

這裡寫圖片描述

增加屬性,訪問屬性

我們要為建立的物件增加屬性和訪問屬性的值

使用.操作符增加屬性

JavaScript是弱型別的語言,可以動態的新增屬性。


    obj.age = 20;
    obj.name = "zhongfucheng";
    obj.say = function () {
        alert("hello");
    };

複製程式碼

測試

這裡寫圖片描述


使用.操作符訪問屬性


    var aa = obj.age;
    var bb = obj.name;

複製程式碼

測試

這裡寫圖片描述


使用[]操作符訪問屬性


    var aa = [obj["age"]];
    var bb = [obj["name"]];

複製程式碼

測試

這裡寫圖片描述


建立類

方式①

使用function來模擬建立類,function充當了建構函式


		//測試函式
        function test() {

            var teacher = new Teacher();

        }

		//使用function來模擬類
        function Teacher() {

        }
複製程式碼

測試

這裡寫圖片描述


方式②

上面的function來模擬類很容易和函式混淆。

我們一般這樣做:用一個變數記住一個匿名的function當做是類,function充當了建構函式


        function test() {

            var teacher = new Teacher();
            
        }
        var Teacher = function () {


        };

複製程式碼

測試

這裡寫圖片描述


方式③

使用JSON語法來建立類,也就是物件直接量定義方法



        var obj = {
            age: 20,
            str: "zhongfucheng",
            method:function () {
                alert("aaa");
            }

        };
複製程式碼

測試

這裡寫圖片描述


公有屬性和方法

我們建立公有屬性應該在類中指定,建立公有方法應該使用原型物件prototype

prototype定義的屬性就類似於Java的靜態成員:在原型物件上定義了屬性,擁有這個原型物件的function所建立的物件也擁有定義的屬性!所以,我們方法中就使用prototype


        var obj = function Teacher(name) {
            this.name = name;
            if( typeof obj._init=="undefined") {
                obj.prototype.setName = function (name) {
                    this.name = name;
                };

                obj.prototype.getName = function () {
                    alert(this.name);
                };
            }

            obj._init = true;
        };

複製程式碼

建立兩個不同的Teacher物件,name屬性是不一樣的。而它們共享同一份setName()和getName()方法

這裡寫圖片描述

值得注意的是:prototype定義的屬性只可讀的。如果你想要使用具體物件寫prototype的屬性,實際上並不是寫,而是重新為該類定義了一個同名(和prototype同名)的屬性。在讀取同名屬性的時候,優先讀取物件上的屬性,而不是prototype的。


私有屬性

我們在Java中,定義私有屬性是通過關鍵字private來修飾的。。

在JavaScript中是沒有這樣的關鍵字的,我們需要這樣做:定義在方法內【也就是function內部,也可以看作成建構函式】的變數,就是私有變數。


        var obj = function Teacher(name) {

            //這是私有屬性,外界不能訪問
            var age = 23;

            //這是公有屬性,外界可以訪問
            this.name = name;
            
            //想要訪問私有變數age,只能在這裡編寫方法來訪問。其餘的地方都不行!

			//我們通常就是在這裡編寫公有方法來訪問私有屬性

        };

複製程式碼

靜態屬性和方法

在JavaScript中定義靜態屬性其實就是通過prototype原型物件來定義的

定義靜態的時機:

  • 當類的某個值與物件無關期望所有位置看到的結果是一樣的時候,就可以定義為類靜態屬性
  • 如果類的一個方法做的是和具體物件無關的操作,而是做一些工作操作的時候,就可以將這個方法定義為靜態的類方法
	//靜態屬性TYPE
	Book.TYPE = “IT”;

	Book.print = function(){alert(Book.TYPE);}

複製程式碼

JavaScript中的for in迴圈

在學習AJAX的時候,發現JavaScript中for in迴圈,這種迴圈對於遍歷JSON是很好用的。於是寫下了這篇博文

for in迴圈本質上是forEach迴圈,它主要有兩個作用

  • 遍歷陣列
  • 遍歷JavaScript物件

遍歷陣列

當使用for in來遍歷陣列的時候,它的迴圈計數器是陣列元素的索引值


    var a = ['a', 'b', 'c'];
    for(var index in a) {
        alert(index);
    }


複製程式碼

效果:

這裡寫圖片描述

遍歷JavaScript物件

當使用for in來遍歷物件的時候,它的迴圈計數器是物件的屬性名


	//物件json上,包含了兩個物件a和b屬性
    var json = {a:{num:1},b:{num:2}};

    for(var name in  json){
        alert(name);
    }

複製程式碼

效果

這裡寫圖片描述


JS打氣球遊戲

在B站中看見了一個JS大氣球這麼一個教程,才知道原來JS+HTML5+CSS3能那麼有趣。但是視訊中沒並沒有給出原始碼。於是在別人的部落格中搜到了對應的原始碼以及他自己實現的思路,該博主對其進行了改編。

www.cnblogs.com/morang/p/76…

以上的博文有原始碼的下載。下面我就直接貼上原始碼了。思路就在博文中。


<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
	<head>
		<title>氣球大戰</title>
		<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0">
		<style>

		/*CSS3能夠將氣球描繪出來,使用到了圓形、旋轉、陰影等技術*/
			body{margin:0px;padding:0px;}
			#ballDiv{position: fixed;top: 0;left: 0;}
			.balloon{
				width:150px;
				height:150px;
				position:absolute;
				left:0px;
				top:0px;
				background-color:#f3778d;
				border-radius:50% 50% 10% 50%;
				transform:rotate(45deg);
				box-shadow:1px 1px 20px 20px pink inset;
				z-index:10;
			}
			/*這裡使用到了偽元素,可以不用到html中定義元素就可以實現功能了!*/
			.balloon:after{
				width:20px;
				height:20px;
				content:"";
				display:block;
				background:transparent;
				position:absolute;
				right: -15px;
				bottom: -15px;
				border-left:5px solid pink;
				border-top:5px solid pink;
			}
			/*這裡使用到了偽元素,可以不用到html中定義元素就可以實現功能了!*/
			.balloon:before{
					width: 2px;
					height: 50px;
					content: "";
					display: block;
					background: #ffc0cb;
					position: absolute;
					right: -10px;
					top: 100%;
					margin-top: -16px;
					transform: rotate(-45deg);
			}
		</style>
	</head>
	<body>
		<div id="gameinfo" style="transform: translateZ(360px);">
			<p>
				最高連擊:<span id='maxDoubleHit'>0</span>				
			</p>
			<p>
				本次遊戲:<span id='currentDoubleHit'>0</span>				
			</p>
			<p id="gamemsg" style="display:none;">
				<span style="color:red;font-weight:bold;">
					Game Over
				</span>
				<button onclick="javscript:location.reload();">
					重新開始
				</button>
			</p>
		</div>
		<div id="ballDiv">
			
			
		</div>
		<!--<div class="balloon"></div>-->
		<script>
			var maxDoubleHit=localStorage.getItem('eliminateCount')||0
			var currentDoubleHit=0
			//當做一個快取池,優化效能的。
    		var bnElements=[];//存放所有氣球
			var random=Math.random;//隨機函式
			var wW=window.innerWidth;//視窗寬度
			var wH=window.innerHeight;//視窗高度
			var ballW=160;//氣球的寬度
			var ballH=300;//氣球的寬度
			var minSpeed=3;//最小速度,每次向上移動至少3px
			var speedNum=5;//速度的定量
			var defBnNumber=5;//初始化氣球
			var moveTimer;
			var isEnd=false;			
			var jindex=1;
			var ballDiv=document.getElementById('ballDiv');
			
			//初始化			
			init(defBnNumber);
			//移動
			move();
			//繫結單擊事件
			bindClick();
			
			//遊戲資訊
			document.getElementById('maxDoubleHit').innerText=maxDoubleHit
			function record(){
				if(isEnd){
					clearTimeout(moveTimer);
					bnElements=[];
					document.getElementById('gamemsg').style.display='block';
					document.getElementById('gameinfo').style='transform: translateZ(360px);position: fixed;top:0;left:0;z-index:999';
				}
				else{
					init(1);
					document.getElementById('currentDoubleHit').innerText=++currentDoubleHit;
					if(currentDoubleHit>maxDoubleHit){
						document.getElementById('maxDoubleHit').innerText=currentDoubleHit;
						localStorage.setItem('eliminateCount',currentDoubleHit)
					}
				}
			}
    		//初始化氣球
			function init(num){
				//建立一個虛擬文件節點
				var docFragment=document.createDocumentFragment();
				for(var i=0;i<num;i++){
					var bnElement=document.createElement('div');
					bnElement.className='balloon';
					//速度隨機,限定最小值
					var speed=Math.max(minSpeed,~~(random()*speedNum));
					bnElement.setAttribute('speed',speed);//~~取整 移動速度
					bnElement.setAttribute('id','ball-'+jindex++);
					//分散排列
					var x=(~~(random()*wW))-ballW;
					x=Math.max(0,x);
					bnElement.style.left=x+'px';				
					bnElement.style.top=wH+'px';//露一點出來			
					
					//1.先將建立的氣球放入建立的虛擬文件節點
					docFragment.appendChild(bnElement);
					bnElements.push(bnElement);
				}
				//2.將虛擬文件節點新增到body中
				ballDiv.appendChild(docFragment);
			}

			//使用定時器來對氣球進行移動。
			function move(){
				var bl=bnElements.length
				for(var i=0;i<bl;i++){
						var currentElement=bnElements[i]
						if(currentElement==null){
							continue;
						}
						var offsetTop=currentElement.offsetTop;
					if(offsetTop>0){//視窗中

							//offset就是針對視窗的位置來進行移動的。
							var speed=currentElement.getAttribute('speed');
							currentElement.style.top=offsetTop-speed+'px'
						}
						else{
							//移除dom節點
							//ballDiv.removeChild(currentElement);
							//移除陣列中
							//bnElements.splice(i,1);
							//init(1);
							isEnd=true;
							record();
						}
				}
				moveTimer=setTimeout(move,1000/30);
			}

			//對所有的氣球進行單擊監聽事件,不要單獨為每個氣球來進行監聽,這樣耗費效能!
			function bindClick(){
			
				ballDiv.addEventListener('click',clickFunc,false);
				function clickFunc(e){
					if(!isEnd && e.target.className=='balloon'){
						bnElements.splice(bnElements.lastIndexOf(e.target),1);

						//這裡使用call主動呼叫,在boom方法中我們就可以使用this指標了。
						boom.call(e.target,function(){
							e.target.parentNode.removeChild(e.target);
							record();
						});
					}
				}
			}
			function boom(callback){
				//var that=this; //替換了上下文,但是沒有使用this的意義.
				var speed=this.getAttribute('speed');
				this.timer=setInterval(function(){
					this.style.opacity=0.1*(speed--)
					if(speed<1){
						callback&&callback();
						clearInterval(this.timer);
					}
				}.bind(this),30);
			}
			
		</script>
	</body>
</html>
複製程式碼

看了視訊也學到了之前一直沒有注意的東西:

  • CSS3很厲害啊,能將方形的div轉成是橢圓形的[也就是氣球的形狀],還有盒子的陰影設定。
  • 使用偽元素就可以不用直接在html中設定標籤了。配合CSS3也能夠做出對應的樣式。
  • 使用實體邊框配合CSS3也可以做出不同的形狀樣式
  • 在生成元素的時候,可以先將要生成的元素加入到文件片段中,再使用文件片段來進行一次性新增到body上,這樣效能會好很多!
  • 使用~~運算子能夠取整數
  • 限定氣球的邊界就可以使用max和min函式來進行限定。這也是很好用的。
  • 移動氣球我們需要用到定時器。
  • 使用call主動呼叫方法,把目標物件傳遞過去的話,我們就可以使用this指標了。
  • 在定時器中使用bind(this),就可以在定時器中使用this指標的,因為定時器預設是由瀏覽器window來進行呼叫的,預設是不能使用this的
  • 繫結單擊事件的時候,不要使用迴圈來進行繫結,這樣太耗費效能了,我們可以使用監聽事件來進行一次繫結。
  • 在遍歷元素陣列的時候,條件是元素陣列的長度時,我們可以先把該元素陣列的長度初始化出來,那麼也可以提升效能!不然就每次判斷前都要去查詢資料的長度!

for(var i=0,len = array.length; i<len;i++){}
複製程式碼

如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y

相關文章