前端学习笔记JavaScript - 类和对象

三大特性

封装

封装性就是隐藏实现细节,仅对外提供接口。

        function Test() {
            this.name = 1; // -- 私有属性,外部无法访问
            let age = 30; // -- 私有属性,外部无法访问
            // -- 提供共有方法设置属性
            this.setAge =  function (myAge) {
                if (myAge > 0 ){
                    age = myAge;
                }
            }
            // -- 提供公有方法获取属性
            this.getAge = function () {
                return age;
            }
            // -- 私有方法
            function say() {
                console.log("唱歌");
            }
        }

        let obj1 = new Test();
        obj1.name = "zs";
        obj1.setAge(23);
       console.log(obj1.getAge());

属性和方法的分类

  • 实例属性/实例方法

通过实例对象访问的属性 - 实例属性

通过实例对象调用的方法 - 实例方法

  • 静态属性/静态方法

通过构造函数访问的属性 - 静态属性

通过构造函数调用的方法 - 静态方法

        function Person(myName) {
            this.name = myName;
            this.say = function () {
                console.log("唱歌");
            }
        }

        let obj1 = new Person("zs")
        // -- 实例属性
       console.log(obj1.name);
        // -- 实例方法
        obj1.say();

        // -- 静态属性
        Person.age = 12;
       console.log(Person.age);
       // -- 静态方法
        Person.run = function () {
            console.log("跑");
        }
        Person.run();

继承

bind - call - apply

用于修改函数中的this

bind

修改函数或方法中的this为指定对象,并会返回一个修改之后的新函数。

注意:bind除了可以修改this以外,还可以传递参数,只不过参数必须写在this对象后面。

        let obj = {
            name: "zs"
        }

        function Person(myName,myAge) {
            console.log(myName);
        }

        let fn = Person.bind(obj,"ls",12);
        fn()

call

修改函数或方法中的this为指定对象,并会立即调用修改后的函数。

注意:bind除了可以修改this以外,还可以传递参数,只不过参数必须写在this对象后面。

        let obj = {
            name: "zs"
        }

        function Person(myName,myAge) {
            console.log(myName);
        }

        Person.call(obj,"ls",12);

apply

修改函数或方法中的this为指定对象,并会立即调用修改后的函数。

注意:bind除了可以修改this以外,还可以传递参数,只不过参数必须写在this对象后面。(参数传递格式和call不一样,其他都一样)

        let obj = {
            name: "zs"
        }

        function Person(myName,myAge) {
            console.log(myName);
        }

        Person.apply(obj,["ls",12]);
 
  • 继承方式
  1. 在子类的构造函数中通过call借助父类的构造函数
  2. 将子类的原型对象修改为父类的实例对象
        function Person(myName,myAge) {
            this.name = myName;
            this.age  = myAge;
            this.go = function () {
                console.log("gogogo");
            }
        }

        Person.prototype.run = function () {
            console.log("运动会");
        }

        Person.prototype.height = 175;
        
        function Student(myName,myAge,mySourde) {
            // -- 在子类的构造函数中通过call借助父类的构造函数
            Person.call(this,myName,myAge);
            this.sourd = mySourde;
            this.say = function () {
                console.log("好好学习");
            }
        }

        // -- 将子类的原型对象修改为父类的实例对象 , 就可以访问父类的prototype的属性和方法
        Student.prototype = new Person();
        Student.prototype.constructor = Student;

        let  xiaoMing = new Student("XH",12,99);
       console.log(xiaoMing.name + xiaoMing.age + xiaoMing.sourd);
       xiaoMing.say();
       xiaoMing.go();
       xiaoMing.run();
       console.log(xiaoMing.height);

多态

ES6类和对象

ES6中定义类

注意

  • 在ES6标准中,添加实例属性都需要再constructor中添加
               class Person {
           // -- 传递参数
           constructor(myName,myAge) {
               // -- 实例属性
               this.name = "zs";
               this.age  = 11;
               // -- 实例方法
               this.run = function () {
                   console.log("跑");
               }
           }

           // -- 实例方法(添加到原型中)
           say(){
               console.log(this.name,this.age);
           }
           // -- 静态方法
           static eat(){
               console.log("回锅肉");
           }

       }

       let xiaoMing = new Person("zs",12);
       xiaoMing.say();
       xiaoMing.run();

       Person.love = 175;
       Person.eat();
      console.log(Person.love);

ES6继承

        class Person {
            constructor(myName,myAge) {
                this.name = myName;
                this.age  = myAge;
            }
            say(){
                console.log(this.name, this.age);
            }
        }

        // -- Student继承Person
        class Student extends Person {
            constructor(myName,myAge,mySoure) {
                // -- 在子类中通过call,bind借助父类的构造函数
                super(myName,myAge);
                this.soure = mySoure;
            }
        }

        let stu = new Student("ls",44,100);
        stu.say();

获取对象的真实类型

        let list = [];
        let obj = {};

        console.log(list.constructor.name);
        console.log(obj.constructor.name);

instanceof

判断对象是否是指定函数的实例

        function Person() {

        }

        function Student() {

        }

        let p = new Person();
        let s = new Student();

       console.log(p instanceof Person);
       console.log(s instanceof Person);

isPrototypeOf

isPrototypeOf用于判断一个对象是否是指定对象的原型

        function Person() {

        }

        function Student() {

        }

        let p = new Person();
        let s = new Student();

       console.log(Person.prototype.isPrototypeOf(p));
       console.log(Person.prototype.isPrototypeOf(s));

判断对象属性

in

既会判断类中有没有对应的属性,还会判断prototype中是否有对应属性。


        function Person() {
            this.name = 'ZS';

        }

        Person.prototype.age = 12;


        let p = new Person();
       console.log("name" in p);
       console.log("age" in p);
       console.log("height" in p);

hasOwnProperty

只会判断类中是否有对应属性


       function Person() {
           this.name = 'ZS';

       }

       Person.prototype.age = 12;

       let p = new Person();
       console.log(p.hasOwnProperty("name"));
       console.log(p.hasOwnProperty("age"))

对象遍历

使用for in 循环来遍历obj,取出所有的属性和方法

注意点:无法取出原型对象中的属性和方法。

        function Person(myName, myAge){
            this.name = myName;
            this.age = myAge;
            this.say = function(){
                console.log(this.name, this.age);
            }
        }
        let p = new Person("LNJ", 34);
        console.log(p);
        for(let key in p){
            if(p[key] instanceof Function){
                continue;
            }
            // console.log(key); // name / age / say
            // 注意点: 以下代码的含义取出p对象中名称叫做当前遍历到的名称的属性或者方法的取值
            console.log(p[key]); // p["name"] / p["age"] / p["say"]
            // 注意点: 以下代码的含义取出p对象中名称叫做key的属性的取值
            // console.log(p.key); // undefined
        }

对象的解构赋值

注意点:在对象解构赋值中, 左边的变量名称必须和对象的属性名称一致, 才能解构出数据

        let {name,age} = {name:"zs",age:12}
       console.log(name, age);

深拷贝和浅拷贝

  • 深拷贝

修改新变量的值不会影响原有变量的值

默认情况下基本数据类型都是深拷贝


        let num1 = 11;
        let  num2 = num1;
        num2 = 34;
       console.log(num1, num2);

  • 浅拷贝

修改新变量的值会影响原有变量的值

默认情况下引用类型都是浅拷贝

       let obj = {
           name:"zs",
           age:12
       }

       let obj1 = obj;
       obj1.name = "ls";

       console.log(obj.name, obj1.name);

  • assign()

assign方法可以把第二个参数的对象和方法拷贝到第一个对象中

       let obj = {
           name:"zs",
           age:12
       }
       let obj1 = new Object();
       Object.assign(obj1,obj)
       obj1.name = "ls";
       console.log(obj.name, obj1.name);
  • 对象深拷贝
        class Person{
            name = "lnj";
            cat = {
                age : 3
            };
            scores = [1, 3, 5];
        }
        let p1 = new Person();
        let p2 = new Object();
        depCopy(p2, p1);
        // console.log(p2);

        p2.cat.age = 666;
        console.log(p1.cat.age);
        console.log(p2.cat.age);

        function depCopy(target, source) {
            // 1.通过遍历拿到source中所有的属性
            for(let key in source){
                // console.log(key);
                // 2.取出当前遍历到的属性对应的取值
                let sourceValue = source[key];
                // console.log(sourceValue);
                // 3.判断当前的取值是否是引用数据类型
                if(sourceValue instanceof Object){
                    // console.log(sourceValue.constructor);
                    // console.log(new sourceValue.constructor);
                    let subTarget = new sourceValue.constructor;
                    target[key] = subTarget;
                    depCopy(subTarget, sourceValue);
                }else{
                    target[key] = sourceValue;
                }
            }
        }

数组高级API

  • 遍历数组 - for of
       for (let num of arr) {
           console.log(num);
       }
  • 遍历数组 - forEach
       let arr = [1,3,4,5];

       arr.forEach(function (listValue,listIndex,list) {
           console.log(listValue, listIndex, list);
       })     


// -- 内部实现方式
			let arr = [1,3,4,5];
       
        Array.prototype.myForEach = function (fn) {
            for (let i = 0; i < this.length; i++) {
                fn(this[i], i, this);
            }
        }

       arr.myForEach(function (listValue,listIndex,list) {
           console.log(listValue, listIndex, list);

       })
  • 查找元素 - findIndex
        // 1.数组的findIndex方法
        // findIndex方法: 定制版的indexOf, 找到返回索引, 找不到返回-1
        let index = arr.findIndex(function (currentValue, currentIndex, currentArray) {
            // console.log(currentValue, currentIndex, currentArray);
            // if(currentValue === 6){
            if(currentValue === 10){
                return true;
            }
        });
        console.log(index);
  • 查找元素 - find
        // 2.数组的find方法
        // find方法返回索引, find方法返回找到的元素
        // find方法如果找到了就返回找到的元素, 如果找不到就返回undefined
        let value = arr.find(function (currentValue, currentIndex, currentArray) {
            // console.log(currentValue, currentIndex, currentArray);
            // if(currentValue === 6){
            if(currentValue === 10){
                return true;
            }
        });
        console.log(value);
  • 将满足的元素添加到新的数组 - filter
        // 1.数组的filter方法:
        // 将满足条件的元素添加到一个新的数组中
        let newArray = arr.filter(function (currentValue, currentIndex, currentArray) {
            // console.log(currentValue, currentIndex, currentArray);
            if(currentValue % 2 === 0){
                return true;
            }
        });
        console.log(newArray); // [2, 4]
  • 将满足条件的元素映射到新的数组
        // 2.数组的map方法:
        // 将满足条件的元素映射到一个新的数组中
        let newArray = arr.map(function (currentValue, currentIndex, currentArray) {
            // console.log(currentValue, currentIndex, currentArray);
            if(currentValue % 2 === 0){
                return currentValue;
            }
        });
        console.log(newArray); // [undefined, 2, undefined, 4, undefined]
  • 数组排序
// let arr = ["c", "a", "b"];
        // arr.sort();
        /*
        如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
        如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。
        如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前
        注意点: 如果元素是字符串类型, 那么比较的是字符串的Unicode编码
        */
        /*
        arr.sort(function (a, b) {
            if(a > b){
                return -1;
            }else if(a < b){
                return 1;
            }else{
                return 0;
            }
        });
        console.log(arr);
        */

        /*
        let arr = [3, 4, 2, 5, 1];
        // arr.sort();
        arr.sort(function (a, b) {
            // if(a > b){
            //     return -1;
            // }else if(a < b){
            //     return 1;
            // }else{
            //     return 0;
            // }
            // 规律: 如果数组中的元素是数值类型
            //       如果需要升序排序, 那么就返回a - b;
            //       如果需要降序排序, 那么就返回b - a;
            // return a - b;
            return b - a;
        });
        console.log(arr);
        */

        /*
        let arr = ["1234", "21", "54321", "123", "6"];
        arr.sort(function (str1, str2) {
            // return str1.length - str2.length;
            return str2.length - str1.length;
        });
        console.log(arr);
        */

        let students = [
            {name: "zs", age: 34},
            {name: "ls", age: 18},
            {name: "ww", age: 22},
            {name: "mm", age: 28},
        ];
        students.sort(function (o1, o2) {
            // return o1.age - o2.age;
            return o2.age - o1.age;
        });
        console.log(students); 
posted @ 2020-08-13 14:55  cmg123  阅读(102)  评论(0)    收藏  举报