十二、類和對象進(jìn)階2
1.自執(zhí)行方法
定義一個自執(zhí)行函數(shù)截珍,函數(shù)定義完成后攀甚,自己執(zhí)行一次,函數(shù)名可以省略岗喉,因為沒有任何意義
注意:要以分號結(jié)束秋度,否則可能會影響后面的語句。
(function sayHello() {
? ? console.log('sayHello');
})();
自執(zhí)行函數(shù)的簡寫形式
+ function sayYes() {
? ? console.log('sayYes');
}();
自執(zhí)行函數(shù)钱床,也可以直接定義成箭頭函數(shù)
(()=>{
? ? console.log('aaa');
})()
<!DOCTYPE html>
<html>
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>自執(zhí)行函數(shù)</title>
</head>
<body>
? ? <script>
? ? ? ? function fun(){
? ? ? ? ? ? console.log('Hello');
? ? ? ? }
? ? ? ? fun();
? ? ? ? //自執(zhí)行函數(shù)
? ? ? ? // 注意:要以分號結(jié)束荚斯,否則可能會影響后面的語句。
? ? ? ? (function fun2(){
? ? ? ? ? ? console.log('你好');
? ? ? ? })();
? ? ? ? //+號是自執(zhí)行函數(shù)的簡寫
? ? ? ? +function fun3(){
? ? ? ? ? ? console.log('你好查牌,中國');
? ? ? ? }();
? ? ? ? (()=>{
? ? ? ? ? ? console.log('你好事期,迪麗熱巴');
? ? ? ? })();
? ? </script>
</body>
</html>
2.rest參數(shù)
// ...args 就是rest參數(shù)
function fun1(a,b,c,...args){
? ? console.log(a,b,c);
? ? // arguments 是一個類數(shù)組對象,結(jié)構(gòu)長得像數(shù)組纸颜,其實是一個object對象
? ? console.log(arguments);
? ? // rest參數(shù) 是一個數(shù)組對象兽泣,既然是數(shù)組,就可以直接使用數(shù)組的方法胁孙。
? ? console.log(args);
}
<!DOCTYPE html>
<html>
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>rest參數(shù)</title>
</head>
<body>
? ? <script>
? ? ? ? // 方法的形參前面添加...唠倦,就是方法的rest參數(shù)
? ? ? ? //...xxx 是函數(shù)的rest參數(shù),用于接收剩余的實參涮较,注意:通常情況下rest參數(shù)放在最后面
? ? ? ? //rest參數(shù)稠鼻,解決了函數(shù)中arguments對象不是數(shù)組類型的缺陷
? ? ? ? function fun1(a,b,c,...args){
? ? ? ? ? ? console.log(a,b,c);
? ? ? ? ? ? console.log(args);
? ? ? ? ? ? let arr = args.map(r=>r*2)
? ? ? ? ? ? console.log(arr);
? ? ? ? ? ? // console.log(arguments);
? ? ? ? }
? ? ? ? fun1(100,200,300)
? ? ? ? fun1(100)
? ? ? ? fun1(10,20,30,40,50,60,70,80)
? ? ? ? console.log('------------------------');
? ? ? ? // 在定義函數(shù)時,可以給參數(shù)設(shè)置默認(rèn)值
? ? ? ? function fun2(a,b=200,c=300){
? ? ? ? ? ? console.log(a,b,c);
? ? ? ? }
? ? ? ? fun2(1,2,3)
? ? ? ? fun2(1,2)
? ? ? ? fun2(1)
? ? ? ? fun2()
? ? </script>
</body>
</html>
3.展開運算符
展開運算符就是...狂票,可以將一個數(shù)組全部展開
let arr3 = [...arr1,...arr2]
展開運算符候齿,可以展開對象的全部成員,也可以將一個對象的成員闺属,克隆給另一個對象
let lh2 = {...lh}
展開運算符慌盯,可以將多個對象的成員,合并到一個大的對象中屋剑,后面對象中的成員润匙,如果跟前面對象中的成員同名,會覆蓋前面的
let lxt = {...lh,...gxt}
<!DOCTYPE html>
<html>
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>展開運算符</title>
</head>
<body>
? ? <script>
? ? ? ? let arr1 = [11,22,33]
? ? ? ? let arr2 = [44,55,66]
? ? ? ? let arr3 = arr1.concat(arr2)
? ? ? ? console.log(arr3);
? ? ? ? // ...在這里就是展開運算符唉匾,在這里孕讳,展開運算符用于展開數(shù)組中的所有成員匠楚。
? ? ? ? let arr4 = [...arr1,...arr2]
? ? ? ? console.log(arr4);
? ? ? ? console.log('---------------------------');
? ? ? ? let obj1 = {
? ? ? ? ? ? a:100,
? ? ? ? ? ? b:200
? ? ? ? }
? ? ? ? let obj2 = {
? ? ? ? ? ? c:300,
? ? ? ? ? ? d:400,
? ? ? ? ? ? a:500
? ? ? ? }
? ? ? ? // ...在這里,用于將對象的所有屬性展開厂财,并返回一個全新的對象
? ? ? ? let obj3 = {...obj1,...obj2}
? ? ? ? console.log(obj3);? ? ? ?
? ? </script>
</body>
</html>
4.解構(gòu)賦值
ES6中的解構(gòu)賦值語句芋簿,可以直接將數(shù)組中的每個元素提取出來
方式是:let [變量名1,變量名2,...] = 數(shù)組
ES6中的解構(gòu)賦值語句,可以直接將對象中的每個元素提取出來
方式是:let {name,age,gender,job} = obj
通常情況下璃饱,對象的屬性名稱叫什么与斤,就定義什么名稱的變量去接,如果出現(xiàn)了同名荚恶,可以修改名稱
方式是:let {name,age:age1,gender,job} = obj
在ES6中撩穿,定義對象時,屬性的左右兩邊的表達(dá)式相同時谒撼,可以省略右邊的表達(dá)式食寡,該對象在定義的時候,會自動往父級作用域?qū)ふ彝麑傩悦麑?yīng)的值
<!DOCTYPE html>
<html>
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>解構(gòu)賦值</title>
</head>
<body>
? ? <script>
? ? ? ? //定義變量
? ? ? ? let no = 1001
? ? ? ? let name = '小明'
? ? ? ? let age = 30
? ? ? ? let sex = '男'
? ? ? ? //定義對象
? ? ? ? let stu1 = {
? ? ? ? ? ? //屬性名:屬性值
? ? ? ? ? ? //這里的屬性值是上面定義的變量保存的值
? ? ? ? ? ? no:no,
? ? ? ? ? ? name:name,
? ? ? ? ? ? age:age,
? ? ? ? ? ? sex:sex
? ? ? ? }
? ? ? ? console.log(stu1);
? ? ? ? console.log('-----------------');
? ? ? ? //對象的屬性名和屬性值的標(biāo)識相同時廓潜,可以省略屬性值
? ? ? ? let stu2 = {
? ? ? ? ? ? // 是no:no的簡寫
? ? ? ? ? ? no,
? ? ? ? ? ? name,
? ? ? ? ? ? age,
? ? ? ? ? ? sex
? ? ? ? }
? ? ? ? console.log(stu2);
? ? ? ? console.log('--------------------------------------');
? ? ? ? let stu3 = {
? ? ? ? ? ? username:'小明',
? ? ? ? ? ? userage:30,
? ? ? ? ? ? usersex:'男',
? ? ? ? ? ? car:{
? ? ? ? ? ? ? ? carName:'奔馳',
? ? ? ? ? ? ? ? carPrice:'100W'
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? //過去我們這樣寫
? ? ? ? // let username = stu3.username
? ? ? ? // let userage = stu3.userage
? ? ? ? // let usersex = stu3.usersex
? ? ? ? //現(xiàn)在我們這樣寫(解構(gòu)賦值)
? ? ? ? // usersex:usersex2 表示在解構(gòu)的時候?qū)ψ兞棵M(jìn)行重命名
? ? ? ? let {username,userage,usersex:usersex2} = stu3
? ? ? ? console.log(username,userage,usersex2);
? ? ? ? console.log('-----------');
? ? ? ? // let {car} = stu3
? ? ? ? // let {carName,carPrice} = car
? ? ? ? let {car:{carName,carPrice}} = stu3? //這一行代碼抵皱,最終會編譯成下面的兩行代碼
? ? ? ? // let carName = stu3.car.carName
? ? ? ? // let carPrice = stu3.car.carPrice
? ? ? ? console.log(carName,carPrice);
? ? ? ? let arr = [11,22,33,44,55]
? ? ? ? // 解構(gòu)數(shù)組中的元素,采用的[]
? ? ? ? let [a,b] = arr
? ? ? ? console.log(a,b);
? ? </script>
</body>
</html>
5.值類型和引用類型
在js中辩蛋,number呻畸,string,boolean悼院,都是值類型伤为,值類型的變量,直接將數(shù)據(jù)保存到內(nèi)存的椨8颍空間中钮呀。值類型的變量剑鞍,在傳遞時昨凡,傳的是副本。
在js中蚁署,對象便脊,數(shù)組,都是引用類型光戈,引用類型的變量哪痰,將數(shù)據(jù)保存在堆中,然后將堆的地址保存到棧中久妆。
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>值類型和引用類型</title>
</head>
<body>
? ? <script>
? ? ? ? function upateNum(num2){
? ? ? ? ? ? console.log('num2='+num2);
? ? ? ? ? ? num2+=5
? ? ? ? ? ? console.log('num2='+num2);
? ? ? ? }
? ? ? ? let num1 = 5? //number類型
? ? ? ? // 值類型在調(diào)用方法傳遞是晌杰,傳的是值
? ? ? ? upateNum(num1)
? ? ? ? console.log('num1='+num1);//可以看出num1的值沒變
? ? ? ? console.log('-------------------------');
? ? ? ? function updateArr(arr2){
? ? ? ? ? ? console.log('arr2',arr2);//[11,22,33,44,55]
? ? ? ? ? ? arr2.push(66)//[11,22,33,44,55,66]
? ? ? ? ? ? console.log('arr2',arr2);//[11,22,33,44,55,66]
? ? ? ? }
? ? ? ? //數(shù)組是引用類型
? ? ? ? let arr1 = [11,22,33,44,55]
? ? ? ? updateArr(arr1)
? ? ? ? console.log('arr1',arr1);//此時arr1與arr2的值都變了=>[11,22,33,44,55,66]
? ? </script>
</body>
</html>
6.原型對象
prototype屬性是類的原型對象。通常情況下筷弦,我們習(xí)慣將類的方法肋演,定義到類的原型對象中抑诸,這樣做的好處是,提高代碼的利用率爹殊,不會開辟多余的內(nèi)存空間蜕乡。
__proto__屬性是對象的原型對象,注意:同種類型多個對象上的原型對象 共同指向類型上的原型對象梗夸。類的原型對象上面的方法层玲,類的對象,可以直接調(diào)用
<!DOCTYPE html>
<html>
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>原型對象</title>
</head>
<body>
? ? <script>
? ? ? ? // 構(gòu)造函數(shù)(類)有原型對象反症,其實就是構(gòu)造函數(shù)身上的一個自帶屬性辛块,這個屬性是:prototype
? ? ? ? // 對象也有原型對象,其實就是對象身上的一個自帶屬性铅碍,這個屬性是:__proto__
? ? ? ? // 所有同類型的對象身上的原型對象屬性憨降,都指向類的原型對象屬性。
? ? ? ? // 類和對象的原型對象身上掛的方法该酗,對象可以直接使用授药,不需要經(jīng)過原型對象。
? ? ? ? function Student(name,age,sex){
? ? ? ? ? ? this.name = name
? ? ? ? ? ? this.age = age
? ? ? ? ? ? this.sex = sex
? ? ? ? ? ? // 如果將方法直接定義在類里面呜魄,將來根據(jù)這個類創(chuàng)建的每個對象悔叽,都要創(chuàng)建自己獨立的這些方法
? ? ? ? ? ? // 如果要創(chuàng)建很多對象,對內(nèi)存的開銷會很大爵嗅。
? ? ? ? ? ? /* this.sayHi = function(){
? ? ? ? ? ? ? ? console.log(`Hi娇澎!我叫${this.name},今年${this.age}歲睹晒,性別是${this.sex}`);
? ? ? ? ? ? }
? ? ? ? ? ? this.study = function(time){
? ? ? ? ? ? ? ? console.log(`Hi趟庄!我叫${this.name},我每天學(xué)習(xí)${time}小時`);
? ? ? ? ? ? }
? ? ? ? ? ? this.play = function(time){
? ? ? ? ? ? ? ? console.log(`Hi伪很!我叫${this.name}戚啥,我每天玩${time}小時`);
? ? ? ? ? ? } */
? ? ? ? }
? ? ? ? // 我們可以將類的方法,添加到類的原型對象身上
? ? ? ? Student.prototype.sayHi = function(){
? ? ? ? ? ? console.log(`Hi锉试!我叫${this.name}猫十,今年${this.age}歲,性別是${this.sex}`);
? ? ? ? }
? ? ? ? Student.prototype.study = function(time){
? ? ? ? ? ? console.log(`Hi呆盖!我叫${this.name}拖云,我每天學(xué)習(xí)${time}小時`);
? ? ? ? }
? ? ? ? Student.prototype.play = function(time){
? ? ? ? ? ? console.log(`Hi!我叫${this.name}应又,我每天玩${time}小時`);
? ? ? ? }
? ? ? ? let s1 = new Student('張三',20,'男')
? ? ? ? let s2 = new Student('李四',22,'女')
? ? ? ? let s3 = new Student('王五',24,'男')
? ? ? ? // 查看Student類的原型對象
? ? ? ? console.log(Student.prototype);
? ? ? ? // 查看三個對象的原型對象,一模一樣宙项。
? ? ? ? console.log(s1.__proto__);
? ? ? ? console.log(s2.__proto__);
? ? ? ? console.log(s3.__proto__);
? ? ? ? s1.sayHi()
? ? ? ? s1.study(8)
? ? ? ? s1.play(3)
? ? ? ? console.log('------------------');
? ? ? ? s2.sayHi()
? ? ? ? s2.study(6)
? ? ? ? s2.play(6)
? ? ? ? console.log('------------------');
? ? ? ? s3.sayHi()
? ? ? ? s3.study(10)
? ? ? ? s3.play(1)
? ? </script>
</body>
</html>
7.ES6中定義類的新語法
// 定義一個Person類型
class Person{
? ? // 構(gòu)造函數(shù)
? ? constructor(name,age,gender){
? ? ? ? this.name = name,
? ? ? ? this.age = age
? ? ? ? this.gender = gender
? ? }
? ? // 給類添加一個方法
? ? sayHi = function(){
? ? ? ? console.log(this.name,this.age,this.gender);
? ? }
? ? //用這種方式定義的方法,是將方法定義的類的原型對象中去
? ? sayHello(){
? ? ? ? console.log('hello!');
? ? }
}
8.繼承
<!DOCTYPE html>
<html lang="en">
<head>
? ? <meta charset="UTF-8">
? ? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? ? <meta name="viewport" content="width=device-width, initial-scale=1.0">
? ? <title>Document</title>
</head>
<body>
? ? <script>
? ? ? ? //ES5:
? ? ? ? // 定義一個人類
? ? ? ? function Person1(name, age, gender) {
? ? ? ? ? ? this.name = name
? ? ? ? ? ? this.age = age
? ? ? ? ? ? this.gender = gender
? ? ? ? }
? ? ? ? Person1.prototype.eat = function () {
? ? ? ? ? ? console.log(`我叫${this.name},我在吃飯...`);
? ? ? ? }
? ? ? ? Person1.prototype.say = function () {
? ? ? ? ? ? console.log(`大家好株扛!我叫${this.name} 今年${this.age}歲 性別是${this.gender}`);
? ? ? ? }
? ? ? ? // 通過Person類型尤筐,創(chuàng)建出了兩個對象
? ? ? ? let p1 = new Person1('張三', 20, '男')
? ? ? ? p1.say()
? ? ? ? p1.eat()
? ? ? ? let p2 = new Person1('李四', 21, '男')
? ? ? ? p2.say()
? ? ? ? p2.eat()
? ? ? ? console.log('-------------------------------------');
? ? ? ? //定義了學(xué)生類
? ? ? ? function Student1(name, age, gender, no) {
? ? ? ? ? ? // 繼承Person類的屬性
? ? ? ? ? ? Person1.call(this, name, age, gender)
? ? ? ? ? ? // Student類特有的屬性
? ? ? ? ? ? this.no = no
? ? ? ? }
? ? ? ? // 給Student類的prototype屬性 new一個Person類型的對象
? ? ? ? // 用于繼承Person類的方法
? ? ? ? Student1.prototype = new Person1()
? ? ? ? Student1.prototype.study = function () {
? ? ? ? ? ? console.log(`我叫${this.name},我的學(xué)號是${this.no},我在學(xué)習(xí)...`);
? ? ? ? }
? ? ? ? let s1 = new Student1('王五', 20, '女', '1001')
? ? ? ? s1.study()
? ? ? ? s1.eat()
? ? ? ? s1.say()
? ? ? ? console.log("******************************************************");
? ? ? ? //ES6:
? ? ? ? // 定義人類
? ? ? ? class Person2 {
? ? ? ? ? ? // 定義構(gòu)造函數(shù)
? ? ? ? ? ? constructor(name, age, gender) {
? ? ? ? ? ? ? ? this.name = name
? ? ? ? ? ? ? ? this.age = age
? ? ? ? ? ? ? ? this.gender = gender
? ? ? ? ? ? }
? ? ? ? ? ? // 說話方法
? ? ? ? ? ? say() {
? ? ? ? ? ? ? ? console.log(`大家好邑贴!我叫${this.name} 今年${this.age}歲 性別是${this.gender}`);
? ? ? ? ? ? }
? ? ? ? ? ? // 吃方法
? ? ? ? ? ? eat() {
? ? ? ? ? ? ? ? console.log(`我叫${this.name},我在吃飯...`);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? // 每個類型都一個prototype屬性,我們稱它為類的原型對象叔磷。
? ? ? ? // 類的原型對象上面的成員拢驾,給類的所有實例(實例就是類創(chuàng)建出來的對象)共享。
? ? ? ? console.log(Person2.prototype);
? ? ? ? // 通過Person類型改基,創(chuàng)建出了兩個對象
? ? ? ? let p3 = new Person2('張三', 20, '男')
? ? ? ? console.log(p3);
? ? ? ? p3.say()
? ? ? ? p3.eat()
? ? ? ? let p4 = new Person2('李四', 21, '男')
? ? ? ? console.log(p4);
? ? ? ? p4.say()
? ? ? ? p4.eat()
? ? ? ? console.log('-------------------------------------');
? ? ? ? // extends關(guān)鍵字繁疤,表示繼承
? ? ? ? class Student2 extends Person2 {
? ? ? ? ? ? // 構(gòu)造函數(shù)
? ? ? ? ? ? constructor(name, age, gender, no) {
? ? ? ? ? ? ? ? // 調(diào)用父類的構(gòu)造函數(shù)
? ? ? ? ? ? ? ? super(name, age, gender)
? ? ? ? ? ? ? ? // 學(xué)生特有的屬性
? ? ? ? ? ? ? ? this.no = no
? ? ? ? ? ? }
? ? ? ? ? ? //學(xué)生學(xué)習(xí)的方法
? ? ? ? ? ? study() {
? ? ? ? ? ? ? ? console.log(`我叫${this.name},我的學(xué)號是${this.no},我在學(xué)習(xí)...`);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? let s2 = new Student2('王五', 20, '女', '1001')
? ? ? ? console.log(s2);
? ? ? ? s2.study()
? ? ? ? s2.eat()
? ? ? ? s2.say()
? ? </script>
</body>
</html>