--- tags: JavaScript,第四章 --- # JavaScript第四章-對象 # 對象 對象是一組無序的相關屬性和方法的集合 EX:字符串、數值、數組、函數 屬性:事物的特徵,在對象中用屬性表示(常用名詞) 方法:事物的行為,在對象中用方法表示(常用動詞) 為甚麼需要對象 ``` var arr = ['張三瘋','男',128,154]; ``` 改用對象表達結構 ``` 張三瘋.姓名 = '張三瘋'; 張三瘋.性別 = '男'; 張三瘋.年齡 = 128; 張三瘋.身高 = 154; ``` 變量、屬性、函數、方法 變量:單獨聲明賦值,單獨存在 屬性:對象裡的變量稱屬性,不需要聲明 函數:單獨存在,通過"函數名()"的方式就能調用 方法:對象裡的函數稱方法,不需要聲明,通過"對象.方法名()"的方式就能調用 ## 創建對象object 1.用字面量創建 ``` var obj = { uname: '張三瘋', age: 18, sex: '男', sayHi: function () { console.log('hi~'); } }; console.log(obj.uname); console.log(obj['age']); obj.sayHi(); ``` 2.用new Object創建 ``` var obj = new Object(); obj.uname = '張三瘋'; obj.age = 18; obj.sex = '男'; obj.sayHi = function () { console.log('hi~'); } console.log(obj.uname); console.log(obj['sex']); obj.sayHi(); ``` 3.構造函數 定義 1.構造函數命名名字首字母要大寫 2.構造函數不需要return就能返回結果 3.調用構造函數必須使用new ``` function 構造函數名() { this.屬性 = 值; this.方法 = function() {} } new 構造函數名(); ``` ``` function Star(uname, age, sex) { this.name = uname; this.age = age; this.sex = sex; this.sing = function (song) { console.log(song); } } var ldh = new Star('劉德華', 18, '男'); console.log(typeof ldh); console.log(ldh.name); console.log(ldh.sex); ldh.sing('冰雨'); var zxy = new Star('張學友', 19, '男'); console.log(zxy.name); console.log(zxy.age); zxy.sing('李香蘭'); ``` new關鍵字執行過程 1.new在內存中創造一個空的對象 2.this就會指向剛才創建的空對象 3.執行構造函數代碼,給這個空對象添加屬性和方法 4.返回這個對象 ## 遍歷對象 ``` var obj = { name: 'pink', age: 18, sex: '男' } for (var k in obj) { console.log(k); // k(變量)輸出得到的是屬性名 console.log(obj[k]); // obj[k] 得到的是屬性值 } ``` # 內置對象 對象分為三種:自定義對象、內置對象、瀏覽器對象 自定義對象:JS基礎內容,屬於ECMAScript 內置對象:JS基礎內容,屬於ECMAScript 瀏覽器對象:JS獨有 內置對象四類型:Math、Date、Array、String ## 查文檔 MDN網站 https://developer.mozilla.org/zh-TW/ W3C網站 https://www.w3schools.com/ ## Math.max 用MDN網站 在搜尋欄輸入 Math.max 裡面有一段敘述 語法 Math.max([value1[, value2[, ...]]) 有中括號[]代表元素可有可無 查文檔的目標 1.查閱該方法的功能 2.查看參數的意義和類型 3.查看返回值的意義和類型 4.通過demo進行測試 ## Math Math數學對象不是一個構造函數 所以不需要使用new 直接使用裡面的屬性和方法即可 ``` console.log(Math.PI); //圓周率 console.log(Math.max(1, 99, 2)); // 99 console.log(Math.max(-1, -10)); // -1 console.log(Math.max(1, 99, 'pink')); // NaN console.log(Math.max()); // -Infinity ``` ## 封裝數學對象 ``` var myMath ={ PI: 3.14, max: function(){ var max =arguments[0]; for(var i =1;i<arguments.length;i++){ if(arguments[i]>max){ max=arguments[i]; } } return max; }, min: function(){ var min =arguments[0]; for(var i =1;i<arguments.length;i++){ if(arguments[i]<min){ min=arguments[i]; } } return min; } } console.log(myMath.PI); console.log(myMath.max(1,5,9)); console.log(myMath.min(1,5,9)); ``` ## 常用數學對象 ``` Math.PI; // 圓周率 Math.floor(); // 向下取整 Math.ceil(); // 向上取整 Math.round(); // 四捨五入就近取整(輸入-3.5結果-3) Math.abs(); // 絕對值 Math.max(); // 最大值 Math.min(); // 最小值 ``` ``` console.log(Math.abs(1)); // 1 console.log(Math.abs(-1)); // 1 console.log(Math.abs('1')); // 隱式轉換還是1 console.log(Math.abs('pink')); // NaN ``` ``` console.log(Math.floor(1.1)); // 1 console.log(Math.floor(1.9)); // 1 ``` ``` console.log(Math.ceil(1.1)); // 2 console.log(Math.ceil(1.9)); // 2 ``` 其他數字都四捨五入,但是.5特殊,它往大的取 ``` console.log(Math.round(1.1)); // 1 console.log(Math.round(1.5)); // 2 console.log(Math.round(1.9)); // 2 console.log(Math.round(-1.1)); // -1 console.log(Math.round(-1.5)); // -1(注意) ``` ## random random()返回一個隨機的小數0<=x<1 這個方法不用參數 ``` console.log(Math.random()); ``` 我們想要得到兩個數之間的整數,且包含這兩個數 ``` function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } console.log(getRandom(1, 10)); ``` 隨機點名 ``` function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } var arr = ['一世', '二世', '三世', '四世', '五世']; console.log(arr[getRandom(0, arr.length - 1)]); ``` ## 猜數字遊戲 ``` function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } var random = getRandom(1, 10); while (true) { var num = prompt('猜1~10'); if (num > random) { alert('你猜大了'); } else if (num < random) { alert('你猜小了'); } else { alert('猜對了'); break; } } ``` 作業 ``` function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } var random = getRandom(1, 50); var result = false; for (var i = 10; i > 0; i--) { var num = prompt('猜1~50你還剩' + i + '次機會'); if (num > random) { alert('你猜大了'); } else if (num < random) { alert('你猜小了'); } else { result = true; alert('猜對了'); break; } } if (result == true) { alert('你贏了'); } else { alert('次數用光你輸了'); } ``` 作業進階 ``` function getRandom(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } var random = getRandom(1, 50); var result = false; var min = 1; var max = 50; for (var i = 10; i > 0; i--) { var num = prompt('猜' + min + '~' + max + '你還剩' + i + '次機會'); if (num > random) { max = num; alert('你猜大了'); } else if (num < random) { min = num; alert('你猜小了'); } else { result = true; alert('猜對了'); break; } } if (result == true) { alert('你贏了'); } else { alert('次數用光你輸了'); } ``` ## Date 複習 ``` var arr =new Array(); // 創建一個數組對象 var obj =new Object(); // 創建一個對象實例 ``` Date() 日期對象是一個構造函數 ``` var date = new Date(); console.log(date); var date1 = new Date(2019, 10, 1); console.log(date1); // 竟然是11月,明明輸入的是10月 var date2 = new Date('2019-10-1 8:8:8'); console.log(date2); ``` ### 日期格式化 console.log如果只要一個空格就打空格,不用字符串轉譯字符\b ``` var date = new Date(); console.log(date.getFullYear()); console.log(date.getMonth() + 1); // 月的號碼為0-11比實際月份少1 console.log(date.getDate()); console.log(date.getDay()); // 周日是0 var year = date.getFullYear(); var month = date.getMonth() + 1; var dates = date.getDate(); var arr = [ '星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六' ]; var day = date.getDay(); console.log( '今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day] ); ``` ``` var date = new Date(); console.log(date.getHours()); console.log(date.getMinutes()); console.log(date.getSeconds()); function getTime() { var time = new Date(); var h = date.getHours(); h = h < 10 ? '0' + h : h; var m = date.getMinutes(); m = m < 10 ? '0' + m : m; var s = date.getSeconds(); s = s < 10 ? '0' + s : s; return h + ':' + m + ':' + s; } console.log(getTime()); ``` ### 時間戳 基於1970年1月1日起的毫秒數 ``` // 寫法1 var date = new Date(); console.log(date.valueOf()); // 現在時間距離1970.1.1的總毫秒數 console.log(date.getTime()); // 現在時間距離1970.1.1的總毫秒數 // 寫法2 最常用 var date1 = +new Date(); console.log(date1); // 寫法3 HTML5才新增的 console.log(Date.now()); ``` ### 倒計時 學習公式 d = 秒數/60/60/24 h = 秒數/60/60%24 m = 秒數/60%60 s = 秒數%60 ``` function countDown(time) { var nowTime = +new Date(); // 當前的時間總毫秒數 var inputTime = +new Date(time); // 用戶輸入的時間總毫秒數 var times = (inputTime - nowTime) / 1000; // 剩餘時間總毫秒數 轉成秒數 var d = parseInt(times / 60 / 60 / 24); d = d < 10 ? '0' + d : d; var h = parseInt((times / 60 / 60) % 24); h = h < 10 ? '0' + h : h; var m = parseInt((times / 60) % 60); m = m < 10 ? '0' + m : m; var s = parseInt(times % 60); s = s < 10 ? '0' + s : s; return d + '天' + h + '時' + m + '分' + s + '秒'; } console.log(countDown('2022-12-12 00:00:00')); ``` ## 字符串對象 ### 基本包裝類型 ``` var str = 'andy'; console.log(str.length); ``` 對象才有屬性和方法 複雜數據類型才有屬性和方法 簡單數據類型為什麼會有length屬性呢 基本包裝類型:把簡單數據類型包裝成複雜數據類型 ``` var temp = new String('andy'); str = temp; temp = null; ``` String、Number、Boolean都會進行基本包裝 ### 字符串不可變 ``` var str = 'andy'; console.log(str); str = 'red'; console.log(str); var str = ''; for (var i = 1; i <= 100; i++) { str += i; } console.log(str); ``` 變量str從頭到尾只有一個(永遠佔一空間) 字符串'andy'和'red'其實不會消失 每創造一個字符串就會增加一個永久無法去除的空間 ### 返回索引位置 跟數組索引一樣,沒有該元素就返回-1 ``` var str = '改革春風吹滿地春天來了'; console.log(str.indexOf('春')); console.log(str.indexOf('春', 3)); // 從索引3之後開始查找 console.log(str.lastIndexOf('春')); ``` ### 某字符的位置和次數 ``` var str = 'abcoefoxyozzopp'; var index = str.indexOf('o'); var num = 0; console.log(index); while (index !== -1) { console.log(index); num++; index = str.indexOf('o', index + 1); } console.log('o出現的次數是' + num); ``` :::danger 換成數組做做看 ::: ### 依位置返回字符 ``` // 1.返回指定位置的字符 var str = 'andy'; console.log(str.charAt(3)); for (var i = 0; i < str.length; i++) { console.log(str.charAt(i)); } // 2.返回指定位置字符的ASCII碼 目的:判斷用戶按下甚麼鍵 console.log(str.charCodeAt(0)); // 3.h5新增的方法 console.log(str[0]); ``` ### 統計次數最多字符 ``` /* var o = { age: 18 }; if (o['age']) { console.log('有'); } else { console.log('沒有'); } */ var str = 'abcoefoxyozzopp'; var o = {}; for (var i = 0; i < str.length; i++) { var chars = str.charAt(i); // 這邊不能用o.chars 請複習對象屬性調用 if (o[chars]) { // o[chars]得到的是屬性值 o[chars]++; } else { o[chars] = 1; } } console.log(o); // 遍歷對象 var max = 0; var ch = ''; for (var k in o) { if (o[k] > max) { max = o[k]; ch = k; } } console.log(max); console.log('最多的字符是' + ch); ``` ### 拼接截取字符串 ``` // 1.concat var str = 'andy'; console.log(str.concat('red')); console.log(str.concat('red', '安安')); // 2.substr var str1 = '一二三四五六七八九'; console.log(str1.substr(4, 3)); //索引號4 取3個 ``` :::danger slice(start,end) substring(start,end) ::: ### 替換字符和轉成數組 ``` // 1. var str = 'andyandy'; console.log(str.replace('a', 'b')); var str1 = 'abcoefoxyozzopp'; while (str1.indexOf('o') !== -1) { str1 = str1.replace('o', '*'); } console.log(str1); // 2.字符轉數組 var str2 = 'red,pink,blue'; console.log(str2.split(',')); var str3 = 'red&pink&blue'; console.log(str3.split('&')); ``` :::danger toUpperCase() toLowerCase() ::: # 數據類型內存分配 ## 值類型 簡單數據類型 string number boolean undefined null ``` var timer = null; console.log(typeof timer) // object ``` ## 引用類型 複雜數據類型 用new來創建的對象 Object Array Date ## 棧和堆 簡單數據類型:在棧裡面新增一個小框框存放值,變量再指向它 複雜數據類型:在棧裡面新增一個小框框存放地址(十六進制),地址指向堆裡面的數據 ``` function Person(name) { this.name = name; } function f1(x) { console.log(x.name); //劉德華 x.name = '張學友'; console.log(x.name); //張學友 } var p = new Person('劉德華'); console.log(p.name); //劉德華 f1(p); console.log(p.name); //張學友 ```