JavaScript-对象六

实例属性与实例方法
  • 与绑定实例对象或者this绑定的属性或者方法,只能通过构造函数的实例对象进行获取或者调用
静态属性与静态方法
  • 与构造函数绑定的属性或者方法,只能通过构造函数名称进行获取或者调用
function Person(Name, Age) {
    // 这是实例属性
    this.name = Name;
    // 这是实例属性
    this.age = Age;
    // 这是实例方法
    this.say = function () {
        console.log("我是Person中的方法");
    }
}

// 静态属性
Person.value = "静态名字";
Person.age = "静态年龄";
// 静态方法
Person.test = function () {
    console.log("静态方法");
}
// 只能通过构造函数名称进行获取或者调用
console.log(Person.name, Person.age);
Person.test();

// 只能通过构造函数的实例对象进行获取或者调用
let obj = new Person("lkj", 24);
console.log(obj.name);
console.log(obj.age);
obj.say();

对象的三大特性
  • 封装性:隐藏实现的细节,仅对外公开接口,这样保证了对该对象的管理权,别人不可以随便修改你的属性或者方法,将属性数据隐藏起来,降低了数据被误用的可能
    /*默认的情况下,对象的属性和方法是公开的,只要拿到该对象,
    就能拿到该对象的属性和方法,甚至能修改该对象的属性和方法*/
    function Person(Name, Age) {
        this.name = Name;
        this.age = Age;
        this.say = function () {
            console.log("我是构造函数中的方法");
        }
    }
    var obj = new Person("lkj", 24);
    // 无条件的拿到对象和属性和方法
    console.log(obj.name); 
    console.log(obj.age);
    console.log(obj.say);
    
    // 无条件的修改对象和属性和方法
    obj.name = "zs";
    obj.age = 24;
    obj.say = function () {
        console.log("我是被修改了");
    }
    console.log(obj.name); 
    console.log(obj.age);
    obj.say();
    
    // 如何实现对象封装?
    /*利用局部作用域的效果让对象的属性和方法保存为私有,
    通过公开方法暴露属性的设置或方法的设置,这样就能让人不能随意修改*/
    function Person() {
        var name = "我是默认名";
        var age = "我是默认年龄";
        this.setAge = function (myAge) {
            if (myAge > 0 && myAge < 100) {
                age = myAge
            }
        }
        this.setName = function (myName) {
            name = myName
        }
        this.getAge = function () {
            return age;
        }
        this.getName = function () {
            return name;
        }
    }
    let obj = new Person();
    obj.setAge(-3);
    console.log(obj.getAge());
    // 输出结果为 我是默认年龄
    
    obj.setAge(55);
    console.log(obj.getAge());
    // 输出结果为55
    
    obj.setName("lkj");
    console.log(obj.getName());
    // 输出结果为lkj
    
  • 继承性:一个构造函数的属性和方法可以由另一个一个构造函数创建的实例对象进行继承
    • bind、call、apply方法:修改函数中this指向的
      // 默认情况下在全局作用域内调用函数,this都是window
      function test() {
          console.log(this);
      }
      test();
      // 输出结果为window
      
      // 上面代码可以写成以下代码
      function test() {
          console.log(this);
      }
      
      window.test();
      // 输出结果为window
      
      bind方法
      // bind方法
      // 通过bind方法修改函数this的指向,并且会返回一个修改之后的新函数
      var obj = {
          name: "zs"
      }
      function test() {
          console.log(this);
      }
      
      var fn = test.bind(obj);
      test();
      // 输出结果window
      
      fn();
      // 输出结果 {name: "zs"}
      
      // 证明返回的新函数其中this就是obj
      // 通过bind方法修改this指向,需要手动的调用返回出来的新函数
      
      /*另外bind方法可以修改this之外,还可以传递参数,
      只不过参数要写在this对象的后面用逗号隔开*/
      var obj = {
          name: "zs"
      }
      function test(num1, num2) {
          console.log(num1, num2);
          console.log(this);
      }
      var fn = test.bind(obj, 10, 20);
      fn();
      // 输出的结果 10 20
      // 输出结果 {name: "zs"}
      
      // 参数也可以在返回的新的函数进行传递
      var obj = {
          name: "zs"
      }
      function test(num1, num2) {
          console.log(num1, num2);
          console.log(this);
      }
      var fn = test.bind(obj);
      fn(10, 20);
      // 输出的结果 10 20
      // 输出结果 {name: "zs"}
      
      call方法
      // call方法
      /*修改this的指向,并立即调用原本的函数,它并不会生成新的函数,
      call方法也可以传递参数,只不过参数要写在this对象的后面用逗号隔开*/
      var obj = {
          name: "zs"
      }
      function test(num1, num2) {
          console.log(num1, num2);
          console.log(this);
      }
      var result = test.call(obj, 30, 40);
      console.log(result);
      // 输出结果为undefined,说明call方法不会返回一个新函数
      
      apply方法
      // apply方法
      /*修改this的指向,并立即调用原本的函数,它并不会生成新的函数
      apply方法也可以传递参数,只不过参数要通过数组来传递参数*/
      var obj = {
          name: "zs"
      }
      function test(num1, num2) {
          console.log(num1, num2);
          console.log(this);
      }
      var result = test.apply(obj, [30, 40]);
      console.log(result);
      // 输出结果为undefined,说明apply方法不会返回一个新函数
      
    • bind、call、apply方法应用
      /*以下有两个对象Person和Student,满足student是Person的一个子类的关系,
      即学生也是一个人,也能使用人的属性和方法*/
      
      // 定义一个Person的构造函数
      function Person(name = "我是默认的名字", age = 0, gender) {
          this.name = name;
          this.age = age;
          this.gender = gender;
          this.say = function () {
              console.log(name + "跟你说'您好'");
          }
      }
      
      // 定义一个Student的构造函数
      function Student() {
          /*如果我们想要使用人的属性和方法,而特意的在Studnt构造函数内部,
          重复添加Person的属性和方法就会显得代码冗余*/
          this.name = name;
          this.age = age;
          this.gender = gender;
          this.say = function () {
              console.log(name + "跟你说'您好'");
          }
          // 这是学生特有的方法
          this.study = function () {
              console.log(name + "是学生,要好好学习");
          }
      }
      
      // 使用更改prototype属性更改Student原型对象为Person的实例对象
      
      // 定义一个Person的构造函数
      function Person(name = "我是默认的名字", age = 0, gender) {
          this.name = name;
          this.age = age;
          this.gender = gender;
          this.say = function () {
              console.log(name + "跟你说'您好'");
          }
      }
      
      // 定义一个Student的构造函数
      function Student() {
          // 这是学生特有的方法
          this.study = function () {
              console.log(name + "是学生,要好好学习");
          }
      }
      var myPerson = new Person("zs", 14, "man");
      console.log(myPerson)
      Student.prototype = new Person();
      Student.prototype.constructor = Student;
      var myStudent = new Student();
      console.log(myStudent.name);
      console.log(myStudent.age);
      myStudent.say();
      myStudent.study();
      
      /*弊端
      1.通过这种方式决定人的信息的实参,无论通过Student构造函数传递给Person构造函数
      2.每次想要使用Person构造函数的属性和方法,都必须通过Person构造函数实例话对象,并传递该次人的信息的实参,如果只有一个人还好,但是如果多个人就会造成工作难度的提升*/
      
      // 可以通过bind、call、apply关键字解决
      // 定义一个Person的构造函数
      function Person(name, age, gender) {
          this.name = name;
          this.age = age;
          this.gender = gender;
          this.say = function () {
              console.log(name + "跟你说'您好'");
          }
      }
      // 初次之外,我们还可以联动“对象四的”只是点,让Student构造函数的实例对象也能使用Person构造函数的公共方法
      Person.prototype = {
          constructor: Person,
          cry: function () {
              console.log(name + "正在哭");
          }
      }
      // 定义一个Student的构造函数
      function Student(name = "我是默认的名字", age = 0, gender, score) {
          this.score = score;
      
          // bind方法
          // var result = Person.bind(this, name, age, gender);
          // result();
      
          // call方法
          // Person.call(this, name, age, gender)
      
          // apply方法
          Person.apply(this,[name, age, gender])
      
      
          // 这是学生特有的方法
          this.study = function () {
              console.log(name + "是学生,要好好学习");
          }
      }
      Student.prototype = new Person();
      Student.prototype.constructor = Student;
      var myStudent = new Student("ls", 14, "man", 99);
      console.log(myStudent.name);
      console.log(myStudent.age);
      console.log(myStudent.gender);
      myStudent.say();
      myStudent.study();
      myStudent.cry();
      
  • 多态:事物的多钟状态,多态在编程语言的体现,父类型保存子类型对象,父类型变量当前的保存的对象不同,产生的结果也不同
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容