十一、对象进阶

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>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值