---
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); //張學友
```