JavaScript对象补充

目录

1、创建对象方式一

(1)、利用字面量创建对象

(2)、对象的方法

(3)、枚举(遍历)对象属性

(4)、区分变量和属性,函数和方法

(5)、this的初印象

2、创建对象方式二

3、创建对象方式三

(1)、利用构造函数创建对象

(2)、构造函数(new关键字)的执行流程:

(3)、对象的实例化

(4)、instanceof

(5)、构造函数优化

4、原型对象

(1)、 原型对象定义

(2)、原型对象的作用

(3)、检查对象中是否含有某个属性

(4)、 原型链

5、垃圾回收

6、创建对象方式四 class


1、创建对象方式一

(1)、利用字面量创建对象

对象字面量:就是花括号{}里面包含了表达这个具体事物(对象)的属性和方法

<script>
      var obj = {};//创建一个空对象
      var obj2 = {
              name: "猪八戒",
              age: 28,
              gender: "男",
              sayHi: function () {
                console.log('hi~');
              }
            };
    </script>

注意

对象内的属性或者方法我们采取健值对的形式,

键:值

属性名:属性值

多个属性或者方法中间用逗号隔开,最后一个属性或者方法逗号可以省略

方法冒号后跟的是一个匿名函数

读取对象

调用对象的属性对象名.属性名

对象名['属性名']

调用对象的方法对象名.方法名

<script>
        //读取对象属性
        console.log(obj2.name);
        console.log(obj2['age']);
        //读取对象方法
        obj.sayHi()
    </script>

(2)、对象的方法

函数也可以成为对象的属性,如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象(obj)的方法,调用函数就说调用对象(obj)的方法(method), 但是他只是名称上的区别,跟函数没有其他的区别

<script>
        /* 创建对象一*/
        var obj=new Object();
        //向对象中添加属性
        obj.name="孙悟空";
        obj.age=18;
        //对象的属性值可以是任何的数据类型,也可以是个函数
        obj.sayName=function(){
            console.log(obj.name);
        };
        console.log(obj.sayName);//打印函数属性
        obj.sayName();//调用obj.sayName()函数。也叫调用obj的sayName方法
        /* 创建对象二 */
         // function sayHi(){
        //   console.log('hallo')
        // }
       var obj2={
        name:'小明',
        age:18,
        sex:'男',
        job:123,
        // 第一种写法
        // sayHi:sayHi,
        // 第二种写法
        // sayHi:function(){
        //   console.log(obj2.name)
        // }
        // 第三种写法es6
        sayHi(){
          console.log('hallo')
        }
       };
       console.log(obj2.name)
       console.log(obj2['sex'])
       console.log(obj2.sayHi)
       obj2.sayHi()
    </script>

(3)、枚举(遍历)对象属性

使用for...in 语句

语法:

for(var 变量 in 对象){ }

for...in语句 对象中有几个属性,循环体就会执行几次,每次执行时,会将对象中的一个属性的名字赋值给 变量

<script>
     var obj={
        name:"孙悟空",
        age:18,
        gender:"男",
        address:"花果山"
        };
        console.log(obj.name)
        for(var n in obj){
          console.log('属性名:'+n)//对象中每个属性的名字赋值给n
          console.log('属性值:'+obj[n]);//通过变量n读取属性值, []读取变量                 
      }
    </script>

(4)、区分变量和属性,函数和方法

变量和属性都是用来存储数据的;

变量是单独声明并赋值,使用的时候直接写变量名,是单独存在的;

属性在对象中,不需要使声明,使用时,也是对象.属性,依托对象存在的;

函数和方法都是用来实现某种功能的,可以做某件事,但函数是单独存在的,方法是依托对象存在的

(5)、this的初印象

解析器在调用函数每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this,this是参数,浏览器传输的,直接拿来用的,this指向的是一个对象,这个对象我们称为函数执行的上下文对象。

根据函数的调用方式的不同,this会指向不同的对象:

1:当以函数的形式调用时,this是window

2:当以方法的形式调用时, 谁调用方法,this就是谁

3:当以构建函数的形式调用时,this就是新创建的那个对象,this就是当前对象,我们找的this就是当前作用域取值范围(后面讲到构造函数时,用到的)

<script>
      //需求:可以输出各自obj的名字
          //创建一个fun()函数
          function fun() {
            console.log(this.name);
          }
          //创建两个对象
          var obj = {
            name: "孙悟空",
            sayName: fun,
          };

          var obj2 = {
            name: "沙和尚",
            sayName: fun,
          };
          var name = "全局的name属性";

          fun(); //==window.fun()  以函数的形式调用,this就是window
          obj.sayName(); //孙悟空  以方法的形式调用,this是调用方法的对象
          obj2.sayName(); //沙和尚
    </script>

2、创建对象方式二

使用工厂方法创建对象,通过该方法可以大批量的创建对象

<script>
    //需求:创建一个对象
      var obj = {
        name: "孙悟空",
        age: 18,
        gender: "男",
        sayName: function () {
          alert(this.name);
        },
      }; 
  /* 需求:批量的创建对象
            使用工厂方法创建对象
        */
    function createPerson(name,age,gender){
            //创建一个新的对象
            var obj=new Object();
                //向对象中添加属性
                obj.name=name;
                obj.age=age;
                obj.gender=gender;
                obj.sayName=function(){
                    alert(this.name);
                };
            //将新的对象返回
            return  obj;
        }
        var obj2=createPerson("猪八戒",28,"男");
        var obj3=createPerson("沙和尚",38,"男");
        var obj4=createPerson("白骨精",18,"女");
    </script>

问题:

使用工厂方法创建的对象,使用的构造函数都是Object

所以创建的对象都是Object这个类型

就导致我们无法区分多种不同类型的对象

3、创建对象方式三

(1)、利用构造函数创建对象

构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋值初始值,它综合new运算符一起使用。我们可以把对象中一些公共属性和方法抽取出来,然后封装到这个函数里面

构造函数语法规范:

function 构造函数名(){

        this.属性=值;

        this.方法=function(){}

}

new 构造函数名();

<script>
      function Person(name, age, gender) {
              //alert(this);//this就是新建的对象,然后赋值给per
              this.name = name;
              this.age = age;
              this.gender = gender;
              this.sayName = function () {
                  alert(this.name)
              };
          }
          var per = new Person("孙悟空", 18, "男");
          var per2 = new Person("玉兔精", 16, "女");
          var per3 = new Person("沙和尚", 28, "男");
          console.log(per);
          console.log(per2);
          console.log(per3);
    </script>

注意:

构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写

构造函数和普通函数的区别就是调用方式的不同,普通函数是直接调用,构造函数需要使用new关键字来调用

构造函数创建属性和方法,必须结合this使用,此时的this就是新创建的那个对象;

(2)、构造函数(new关键字)的执行流程:

a:立刻创建一个新的对象

b:将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象

c:逐行执行函数中的代码

d:将新建的对象作为返回值返回

new一个对象时,会在堆中开辟一片区域,new Person()会在堆中开辟一块区域

(3)、对象的实例化

使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类,例如明星汽车设计图纸

我们将通过一个构造函数创建的对象,称为该类的实例,例如刘德华、某一辆宝马车,

我们利用构造函数创建对象的过程,我们也称为对象的实例化

(4)、instanceof

作用:使用instanceof可以检查一个对象是否是一个类的实例

语法:对象 instanceof 构造函数,如果是,则返回true,否则返回false

注意:所有的对象都是Object的后代,所以任何的对象和我们的instanceof 检查时,都是他的

<script>
       console.log(dog instanceof Person);
    </script>

(5)、构造函数优化

以上demo,我们创建一个Person构造函数,在Person构造函数中, 为每一个对象都添加了一个sayName的方法

目前我们的方法是在构造函数内部创建的,也就是构造函数每执行一次就会创建一个新的sayName方法,也是所有实例的sayName都是唯一的,这样就导致了构造函数执行一次就会创建一个新的方法,执行一万次就会创建一万个新的方法,而这一万个对象都是一样的,这是没有必要的,完全可以使所有的对象共享同一个方法

<script>
      function Person(name,age,gender){
             this.name=name;
             this.age=age;
             this.gender=gender;
            // 向对象中添加一个方法
             this.sayNam=fun;
         }
         //将sayName方法在全局作用域中定义
         function fun(){
                 alert("hello大家好,我是"+this.name);
             };
         //创建一个Person实例
         var per=new Person("孙悟空",18,"男");
         var per2=new Person("猪八戒",28,"男");
         per.sayNam();//孙悟空
         per2.sayNam();//猪八戒
         console.log(per.sayNam==per2.sayNam);//true
    </script>

注意:以上优化也有一定的问题,如将函数定义在全局作用域,污染了全局作用域的命名空间

而且定义在全局作用域中也很不安全

案例:

创建一个电脑对象,该对象要有颜色、重量、品牌、型号、可以看电影,听音乐、打游戏、敲代码

<script>
// 创建一个电脑对象
    var computer = {
      color: '黑色',
      weight: '2.5kg',
      brand: '联想',
      model: 'ThinkPad T480',
      // 看电影的方法
      watchMovie: function() {
        console.log('正在播放电影...');
      },
      // 听音乐的方法
      listenMusic: function() {
        console.log('正在播放音乐...');
      },
      // 打游戏的方法
      playGame: function() {
       console.log('正在玩游戏...');
      }
    };

    // 使用电脑看电影
    computer.watchMovie();
    // 使用电脑听音乐
    computer.listenMusic();
    // 使用电脑打游戏
    computer.playGame();
</script>

4、原型对象

(1)、 原型对象定义

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象(prototype是属性名,它的值是一个对象,这个对象叫原型对象),默认情况下,它是一个空对象

如果我们的函数作为普通函数调用,prototype没有任何作用,

当函数以构造函数的形式调用时,它所创建的对象都会有一个隐含的属性,指向该构造函数的原型对象,我们通过__proto__来访问该属性

(2)、原型对象的作用

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置到原型对象中,当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有就直接使用,如果没有就去原型对象中寻找,然后使用。

以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数中,这样就不用分别给每一个对象添加,也不会影响到全局作用域,就可以使每个对象,都具有这样的属性和方法了

<script>
      //创建函数
      function MyClass() {}
      //向MyClass的原型对象中添加属性a
      MyClass.prototype.a = 123;
      //向MyClass中添加一个方法
      MyClass.prototype.sayHello = function () {
        alert("hello");
      };
      //console.log(MyClass.prototype, );

      //添加实例
      var mc = new MyClass(); //隐含属性__proto__
      var mc2 = new MyClass();

      console.log(MyClass.prototype,"MyClass.prototype");//object
      console.log(mc.__proto__,'mc.__proto__');//object
      // console.log(MyClass.prototype==mc.__proto__);//true
      //  mc.sayHello();
      /*简单理解: 
       MyClass 是mc,mc2的祖先,祖先有一个宝藏,里面放一些宝藏,
         它的后代都可以看到,如果后代本身就有这个宝藏,就不用祖先藏宝库里,没有就用
       */
    </script>

(3)、检查对象中是否含有某个属性

a:使用in检查对象中是否含有某个属性时,如果对象中没有,原型中有,也会返回true

b:可以使用对象的hasOwnproperty()来检查对象自身中是否含有该属性,使用该方法只有当对象自身中含有属性时,才会返回true

<script>
      /* 创建一个构造函数 */
      function MyClass() {}
      //向MyClass的原型中添加一个name属性
      MyClass.prototype.name = "我是原型中的name";
      var mc = new MyClass();
      mc.age = 18;
      console.log(mc.name);
      console.log("name" in mc); //true
      console.log(mc.hasOwnProperty("name")); //false
    </script>

(4)、 原型链

原型对象也是对象,所以它也有原型

当我们使用一个对象的属性或方法时,会先在自身中寻找,自身中如果有,则直接使用,如果没有,则去原型对象中寻找,如果原型对象中有,则使用,如果没有,则去原型对象的原型中寻找,直到找到Object对象的原型,Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined

(具体在js高级的时候讲述)

<script>
       /* toString是属于Object原型上的一个方法。
      toString返回 '[object type]' 其中type是对象的类型,type的值可以是Object, */
      var obj = { sex: "男" };
      console.log(obj.toString());// [object Object]
      //返回来的确实是返回一个【表示对象】的【字符串】
</script>

5、垃圾回收

就像人生活时间长了,会产生垃圾一样,程序运行过程中,也会产生一些垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生的垃圾

当一个对象没有任何的变量或者属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾这种对象过多,会占用我们大量的内存空间,导致我们程序运行变慢,这种垃圾我们必须清理

在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收

我们需要做的只是将不再使用的对象设置null即可

<script>
        var obj=new Object();
       //对对象进行各种操作
       obj.prototype=123;
       console.log(obj.prototype)
       obj=null;
    </script>

6、创建对象方式四 class

JavaScript 语言中,生成实例对象的传统方法是通过构造函数,

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

class初体验

<script>
      // //es5通过构造函数实现
      // function PersonO(username, password) {
      //   this.username = username;
      //   this.password = password;
      // }
      // // 添加方法
      // PersonO.prototype.getstr = function () {
      //   console.log("用户名:" + this.username + ",密码:" + this.password);
      // };
      // // 实例化对象
      // const po1 = new PersonO("章三", "abc123");
      // console.log(po1);
      // po1.getstr();

      // es6实现  class方法实现
      class PersonN {
        //构造方法  constructor名字不能修改
        // 当我们new实例对象的时候,这个方法自动执行
        constructor(username, password) {
          this.username = username;
          this.password = password;
        }
        //方法必须使用该语法, 不能使用 ES5 的对象完整形式
        getstr() {
          console.log("用户名:" + this.username + ",密码:" + this.password);
        }
        //ES5 的对象完整形式  报错
        // getstr:function () {}
      }
      const pn1 = new PersonN("123456", "789012");
      pn1.getstr();
    </script>

说明:使用class关键词 声明类,constructor为构造方法,一个类必须有constructor()方法,

如果没有显式定义,一个空的constructor()方法会被默认添加,

this关键字则代表实例对象,getstr()为普通方法,不要用es5完整写法,getstr()存在 prototype上。

pn1.constructor === pn1.prototype.constructor // true

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值