2021-11-28

十一、对象进阶

1.this

(1).构造函数里面的this,用于给类定义成员(属性和方法)

(2).方法里面的this,指向方法的调用者

(3).箭头函数中没有this,如果在箭头函数中使用了this,会向外层寻找this的指向

(4).如果所有的外层都没有this,最终会指向window对象

注意:用于var定义的成员(变量和方法)都会成为window对象的成员

解决this指向问题:

方式一:备份this

方式二:使用箭头函数

<!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>this1</title>

</head>

<body>

    <script>

        // 注意:构造函数不能使用箭头函数定义

        function Person(name,age){

            // 在构造函数中,this关键字,用于给类添加成员

            this.name = name

            this.age = age

            this.sayHi = function(){

                console.log(`大家好!我叫${this.name},今年${this.age}岁`);

            }

        }

        // 创建对象,该对象会拥有,类型中定义的所有成员。

        let p1 = new Person('张三',20)

        console.log(p1);

        p1.sayHi()

        let p2 = new Person('李四',24)

        console.log(p2);

        p2.sayHi()

        console.log('-----------------------------------------');

        let obj1 = {

            //对象的两个属性

            name:'李白',

            age:20,

            //对象的方法

            sayHi:function(){

                // 在方法中,this指向方法的调用者,谁在调用该方法,this就指向谁

                // 如果一个方法,不是由对象调用执行的,而是直接执行的,那么该方法里面的this就执行window对象

                console.log(`Hi!我是${this.name},今年${this.age}岁`);

            },

            sayHello:()=>{

                // 在箭头函数中没有this,如果在箭头函数中使用了this,它会向上一层函数中去找this

                // 如果上一层函数也是箭头函数,或者没有上一层函数了,这个时候this就指向window对象。

                console.log(`Hello!我是${this.name},今年${this.age}岁`);

            }

        }

        obj1.sayHi()

        let obj2 = {

            name:'杜甫',

            age:22,

        }

        //可以将obj1的函数传给obj2,其实是obj2的sayHi方法,指向obj1的方法

        obj2.sayHi = obj1.sayHi

        obj2.sayHi()

        //将obj1身上的函数,传给了一个sayHi变量

        let sayHi = obj1.sayHi

        window.name = '小明'  //设置window对象的name属性

        window.age = 22        //设置window对象的age属性

        sayHi()

        console.log('-------------------------');

        obj1.sayHello()

        obj2.sayHello = obj1.sayHello

        obj2.sayHello()

        let sayHello = obj1.sayHello

        sayHello()

    </script>

</body>

</html>

<!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>this2</title>

</head>

<body>

    <script>

        // var 定义的成员,会自动添加为window对象的成员

        var address = '北京'

        var showAddress = function(){

            console.log(`地点在${this.address}`);

        }

        console.log(window);

        showAddress()

        window.showAddress()

        console.log('---------------------------------------');

        // 定义一个对象

        let obj1 = {

            name:'张三',

            age:25,

            //自我介绍方法

            sayHi(){

                console.log(`Hi!我叫${this.name},今年${this.age}岁`);

            },

            //显示我的朋友信息

            showMyFriend(){

                // 备份this

                // let that = this

                return {

                    name:'李四',

                    age:22,

                    //自我介绍的方法

                    sayHi(){

                        console.log(`Hi!我叫${this.name},今年${this.age}岁`);

                    },

                    //介绍朋友

                    showMf:()=>{

                        // console.log(`Hi!我的朋友叫${that.name},今年${that.age}岁`);

                        console.log(`Hi!我的朋友叫${this.name},今年${this.age}岁`);

                    }

                }

            }

        }

        obj1.sayHi()

        let obj2 = obj1.showMyFriend()

        obj2.sayHi()  //调用自我介绍的方法

        obj2.showMf() //调用介绍朋友的方法

    </script>

</body>

</html>

2.call apply bind

使用call apply bind更改方法里面this的指向

1.使用call()改变方法里面,this的指向。call()方法的第一个参数必须是指定的对象,方法的原有参数,挨个放在后面

2.使用apply(),也可以改变方法里面this的指向。第一个参是指定的对象,方法的原有参数,统一放到第二个数组参数中。

3.使用bind(),也可以改变方法里面this的指向,用法给call()一样。call()是直接运行方法,bind()是返回新的方法,然后再重新调用。

<!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>call apply bind</title>

</head>

<body>

    <script>

        // call apply bind  更改方法里面this的指向

        let obj1 = {

            name:'张三',

            age:30,

            sayHi(a,b){

                console.log(`Hi!我叫${this.name},今年${this.age}岁。${a}-${b}`);

            }

        }

        let obj2 = {

            name:'李四',

            age:32

        }

        // 使用call()改变方法里面,this的指向

        // call()方法的第一个参数必须是指定的对象,方法的原有参数,挨个放在后面

        obj1.sayHi.call(obj2,200,100)

        let obj3 = {

            name:'王五',

            age:35

        }

        // 使用apply(),也可以改变方法里面this的指向,第一个参是指定的对象,方法的原有参数,统一放到第二个数组参数中

        obj1.sayHi.apply(obj3,[200,100])

        let obj4 = {

            name:'小明',

            age:40

        }

        // 使用bind(),也可以改变方法里面this的指向,用法给call()一样

        // call()是直接运行方法,bind()是返回新的方法,然后再重新调用。

        obj1.sayHi.bind(obj4,200,100)()

    </script>

</body>

</html>

3.将一个对象转为字符串

获取对象的属性值,有两种方式:

1.对象名.属性名

2.对象名["属性名"]

//定义一个手机对象

let phone = {

    name: "小米10",

    color: '红色',

    size: '1000*200*500',

    price: '2999'

}

//转成下面的字符串

//"name=小米10&color=红色&size=1000*200*500&price=2999"

for in 循环,可以循环出对象里面的所有的key,(key就是属性名)

在ES6中新增了获取对象所有key的方法 -> ECMAScript2015 其实就是最新版本的javascript标准

Object.keys(指定的对象),该方法可以获取指定对象的所有key,返回值是一个数组

Object.values(指定的对象),该方法可以获取指定对象的所有的value,返回值是一个数组

<!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 obj1 = {}

        //给对象添加属性有两种方式:

        obj1.name = '张三'

        console.log(obj1);

        obj1['age'] = 20

        console.log(obj1);

        console.log('----------------------------------');

        //定义一个手机对象

        let phone = {

            name: "小米10",

            color: '红色',

            size: '1000*200*500',

            price: '2999'

        }

        //转成下面的字符串

        //"name=小米10&color=红色&size=1000*200*500&price=2999"

        // for in 循环,可以遍历出对象的所有key(key就是属性名称)

        //方式一:

        let arr = []  // 定义一个空数组

        for(let key in phone){

            //获取对象的属性值,可以通过['属性名']

            arr.push(key+'='+phone[key])

        }

        let str = arr.join('&')

        console.log(str);

        //方式二:

        // Object.keys方法,用于返回对象的所有属性名,返回值是一个数组

        let keys = Object.keys(phone)

        // Object.values,用于返回对象的所有属性值,返回值是一个数组

        // let values = Object.values(phone)

        let arr2 = keys.map(function(k){

            return [k,phone[k]].join('=')

        })

        let str2 = arr2.join('&')

        console.log(str2);

        //方法二:简化写法

        let str3 = Object.keys(phone).map(k=>[k,phone[k]].join('=')).join('&')

        console.log(str3);

    </script>

</body>

</html>

4.将字符串转为对象

//定义一个字符串

let str = "name=小米10&color=红色&size=1000*200*500&price=2999"

//转成一个对象

{

    name: "小米10",

    color: '红色',

    size: '1000*200*500',

    price: '2999'

}

<!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 src="./js/bing.js"></script>

    <script>

        //定义一个字符串

        let str = "name=小米10&color=红色&size=1000*200*500&price=2999"

        //转成一个对象

        /* {

            name: "小米10",

            color: '红色',

            size: '1000*200*500',

            price: '2999'

        } */

        let obj = {}  //定义一个空对象

        str.split('&').forEach(r=>{

            let arr = r.split('=')

            // arr=>['name','小米10']

            // obj['name'] = '小米10'

            obj[arr[0]] = arr[1]

        })

        console.log(obj);

        console.log('----------------------------------');

        let obj2 = {

            name:'小明',

            age:20,

            sex:'男',

            job:'教师'

        }

        console.log($b.objectToStr(obj2));

        console.log($b.objectToStr(obj2,'@'));

        console.log($b.objectToStr(obj2,'哈哈'));

        let str2 = 'name=小明&age=20&sex=男&job=教师'

        console.log($b.strToObject(str2));

        console.log($b.strToObject(str2,'&'));

        let str3 = 'name=小李@age=21@sex=男@job=厨师'

        console.log($b.strToObject(str3,'@'));

    </script>

</body>

</html>

5.封装js库

1.isLeepYear 判断是否闰年

2.strReverse 字符串翻转

3.getMiniDate 短日期

4.getChineseDate 中国式日期

5.getPageData 分页方法

6.getStrByObj 对象转字符串

7.getObjByStr 字符串转对象

// 定义一个对象,用于保存所有的工具方法

// 这样做的目的是,防止方法被后引入的库覆盖。

let $b = {

    // 判断是否是闰年的方法

    isLeapYear:(year) => (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0,

    // 对个位数字补零的方法

    repair0:(val) => (val < 10 ? "0" + val : val),

    // 返回一个日期的短日期格式方法

    miniDate:function (date, type){

        let year = date.getFullYear(); //年

        let month = date.getMonth() + 1; //月

        let day = date.getDate(); //日

        let hour = date.getHours(); //时

        let minute = date.getMinutes(); //分

        let second = date.getSeconds(); //秒

        let week = date.getDay(); //周几

        //定义一个返回值,默认拼接:年,月,日

        let ret = [this.repair0(year), this.repair0(month), this.repair0(day)].join("-");

        if (type == "1") {

          ret += " " + [this.repair0(hour), this.repair0(minute), this.repair0(second)].join(":");

        } else if (type == "2") {

          ret +=

            " " +

            [this.repair0(hour), this.repair0(minute), this.repair0(second)].join(":") +

            " 星期" +

            "日一二三四五六"[week];

        }

        return ret;

    },

    // 对字符串反转的方法

    reverseStr:(str) => str.split("").reverse().join(""),

    // 定义一个分页方法,参数是:数组,页码,每页数量

    pageData:function(arr,pageIndex,pageSize){

        let start = (pageIndex-1)*pageSize  //算出起始下标

        let end = start+pageSize  //算出结束下标

        //根据起始下标和结束下标,从原始数组中截取对应的数据并返回

        return {

            //定义返回的数据

            data:arr.slice(start,end),

            //总数量

            count:arr.length,

            //总页数

            totalPage:Math.ceil(arr.length/pageSize),

            //当前页

            pageIndex:pageIndex,

            //每页数量

            pageSize:pageSize

        }

    },

    //将对象转为字符串

    objectToStr:(obj,split='&') => Object.keys(obj).map(k=>[k,obj[k]].join('=')).join(split),

    //将字符串转为对象

    strToObject:(str,split='&')=>{

        let obj = {}  //定义一个空对象

        str.split(split).forEach(r=>{

            let arr = r.split('=')

            obj[arr[0]] = arr[1]

        })

        return obj

    }

}

6.练习题:

1.统计字符串中每个字符串出现的次数

let str = "fasdfsadfsegsageqwgersfdhrhdfsergterwhefweteqheq"

//转成下面格式的对象

{

    a:5,

    b:7,

    c:9,

    ...

}

2.找出出现次数最多的字符

//定义一个对象接收结果

let max = {

    name:'',

    count:0

}

<!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 str = "fasdfsadfsegsageqwgersfdhrhdfsergterwhefweteqheq"

        //对象

        let obj = {}

        // 循环字符串中的所有的字符串

        for(let i=0;i<str.length;i++){

            //根据字符的名称,查找对象中,有没有对应的属性

            if(obj[str[i]]){

                //如果有,对应的属性值加1

                obj[str[i]]++

            }else{

                //如果没有,添加这个属性,属性值赋为1

                obj[str[i]] = 1

            }

        }

        console.log(obj);

        console.log('-----------------------');

        //定义一个出现次数最多的字符对象

        let max = {

            name:'',

            count:0

        }

        Object.keys(obj).forEach(k=>{

            //判断是否有别的字符串大于max

            if(obj[k]>max.count){

                max.name = k

                max.count = obj[k]

            }

        })

        console.log(max);

    </script>

</body>

</html>

7.使用对象数组保存学生信息,实现对学生的增删改查

<!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 studentManager = {

            //定义一个学生数组

            students:[

                {

                    no:'1001',

                    name:'张三',

                    age:22,

                    sex:'男'

                },

                {

                    no:'1002',

                    name:'李四',

                    age:24,

                    sex:'女'

                },

                {

                    no:'1003',

                    name:'王五',

                    age:26,

                    sex:'男'

                }

            ],

            //显示所有学生信息的方法

            show:function(){

                let str = "学号 姓名 年龄 性别\n"

                // 循环出所有的学生信息,并拼接到str中

                this.students.forEach(s=>{

                    str+=`${s.no} ${s.name} ${s.age} ${s.sex}\n`

                })

                alert(str)

            },

            //添加学生信息的方法

            add:function(){

                //输入学生的基本信息

                let no = prompt('请输入学号:')

                //判断学号是否重复

                let index = this.students.findIndex(r=>r.no===no)

                while(index!==-1){

                    no = prompt('学号重复!请重新输入学号:')

                    index = this.students.findIndex(r=>r.no===no)

                }

                let name = prompt('请输入姓名:')

                let age = parseInt(prompt('请输入年龄:'))

                let sex = prompt('请输入性别:')

                // 创建学生对象

                let stu = {

                    no:no,

                    name:name,

                    age:age,

                    sex:sex

                }

                // 将学生对象添加到数组中(学号不能重复)

                this.students.push(stu)

                alert('添加成功!')

            },

            //修改学生信息的方法

            update:function(){

                //输入学生的基本信息

                let no = prompt('请输入学号:')

                //根据学号,到数组中查找并返回指定的学生对象

                let stu = this.students.find(r=>r.no===no)

                //根据学号判断,有没有找到该学生,找到了修改该学生的其他信息,没有找到提示学号不存在

                while(!stu){

                    no = prompt('您输入的学号不存在,请重新输入:')

                    stu = this.students.find(r=>r.no===no)

                }

                stu.name = prompt('请重新输入该学生的姓名:')

                stu.age = parseInt(prompt('请重新输入该学生的年龄:'))

                stu.sex = prompt('请重新输入该学生的性别:')

                alert('修改成功!')

            },

            //删除学生信息的方法

            delete:function(){

                //输入学生的基本信息

                let no = prompt('请输入学号:')

                //查找该学生在数组中的位置

                let index = this.students.findIndex(r=>r.no===no)

                while(index===-1){

                    no = prompt('学号不存在!请重新输入学号:')

                    index = this.students.findIndex(r=>r.no===no)

                }

                this.students.splice(index,1)

                alert('删除成功!')

            },

            //系统主菜单方法

            menu:function(){

                //接收用户的输入

                let no = prompt('*****学生管理系统*****\n1.查询学生 2.添加学生 3.修改学生 4.删除学生 0.退出系统')

                //判断用户输入的是什么

                switch(no){

                    case '1':

                        //调用显示所有学生信息的方法

                        this.show()

                        break;

                    case '2':

                        //调用添加学生信息的方法

                        this.add()

                        break;

                    case '3':

                        //调用修改学生信息的方法

                        this.update()

                        break;

                    case '4':

                        //调用删除学生信息的方法

                        this.delete()

                        break;

                    default:

                        alert('成功退出系统!欢迎下次使用!')

                        return  //跳转整个方法

                }

                // 再次调用自身方法(递归)

                this.menu()

            }

        }

        // 使用学生管理对象,调用menu方法

        studentManager.menu()

    </script>

</body>

</html>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339