5.JS-对象-更多

目录

更多

方法

枚举对象中的属性

作用域

全局作用域

函数(局部)作用域

声明提前

this

工厂方法创建对象

构造函数

创建一个构造函数,专门用来创建不同名称的对象

构造函数的执行流程(系统)

this的情况

构造函数修改

原型对象

原型 prototype

toString

垃圾回收(GC)


更多

方法

  1. 函数也可以成为对象的属性
    1. 如果一个函数作为一个对象的属性保存
    2. 那么我们称这个函数是这个对象的方法
    3. 调用函数我们就说调用对象的方法
  2. 但是它只是名称上的区别,没有其他的不同
<!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>Document</title>
    <script>
        /*
            创建一个对象
        */
        var obj =new Object();
​
        //向对象中添加属性
        obj.name = "孙悟空";
        obj.age = 18;
​
        //对象的属性值可以是任何的数据类型,也可以是个函数
        obj.sayName = function(){
            console.log(obj.name);
        }
        
        function fun(){
            console.log(obj.name);
        }
        // console.log(obj.sayName);
        //调方法
        obj.sayName();   
        //调函数
        fun();
        
    </script>
</head>
<body>
    
</body> 
</html>

枚举对象中的属性

  • 想知道一个已创建好的对象中都有哪些属性
  • 使用for...in 语句
    • 对象有几个属性,循环就会执行几次
    • 每次执行时,都会将对象的一个属性的名字赋值给变量
<!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>Document</title>
    <script>
        var obj ={
            name :"孙悟空",
            age :18,
            gender :"男",
            address:"花果山"
        }
        //枚举对象中的属性
        //使用for...in 语句
        //for...in 语句  对象中有几个属性,循环就会执行几次
        //每次执行时,都会将对象的一个属性的名字赋值给变量
        for(var n in obj){
            console.log("hello");
            console.log(n);
            console.log(obj.n);
            console.log(obj[n]);  //用这种方式可以传递变量
            console.log("***************");
        }
​
    </script>
</head> 
<body>
    
</body>
</html>

使用 in 检查对象中是否含有某个属性

"属性名" in 对象名


作用域

  • 作用域是指一个变量的作用的范围

全局作用域

  1. 直接编写在 script 标签中的 JS 代码,都在全局作用域
    1. 全局作用域在 页面打开时 创建,在 页面关闭时 销毁
    2. 在全局作用域中有一个全局对象 window,
      1. 它代表的时一个浏览器的窗口,它是由浏览器创建,我们可以直接使用
  2. 在全局作用域中
    1. 创建的变量都会作为window对象的属性保存
    2. 创建的函数都会作为window对象的方法保存
  3. 全局作用域中的变量都是全局变量
    1. 在页面的任意部分都可以访问的到
<!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></title>
    <script>
        /*
            在全局作用域中,有一个全局对象window,
                创建的变量都会作为window对象的属性保存
        */
        var a =10;
        console.log(window);
        console.log(a);
        console.log(window.a);
        
        //在全局作用域中,创建的函数都会作为window的方法保存
        function fun(){
            console.log("我是fun函数");
        }
        fun();
        window.fun();
        alert("hello");
        window.alert("hello");
    </script>
</head>
<body>
    
</body>
</html>

函数(局部)作用域

  1. 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁
    1. 每调用一次函数,就会创建一个新的函数作用域,他们之间是互相独立
    2. 在函数作用域中可以访问到全局作用域的变量
    3. 在全局作用域中访问不到局部的变量
      1. 在函数中被创建的变量没办法在全局中被直接访问
    4. 当在函数作用域中直接操作一个变量时,它会先看看自身作用域中是否有该变量,如果有就直接使用,如果没有就在上一级的作用域中寻找
      1. 直到找到全局作用域(最终)中还未找到时,就会报错
    5. 如果在函数中想要直接访问全局的变量,而自身作用域也有该变量时,使用 window.变量 的方式直接访问(使用window对象来访问全局变量)
  • 函数作用域也有声明提前的特性
    • 在函数中,不使用var声明的变量,都会成为全局变量(前提时内部函数没有声明(var)过该变量)
    • 在函数中定义形参,就相当于在函数中已经声明了函数
<!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>Document</title>
    <script>
        /*
            1-函数作用域
        */
​
        function fun(){
            var a=  "我是fun函数中的变量a";
​
            function fun2(){
                var a = "我是fun2函数中的变量a";
                console.log("a = "+a);
            }
            fun2();
        } 
        fun();
​
​
​
        /*
            2- 函数作用域也有声明提前的特性
        */
​
        //【1】在全局作用域中创建一个变量c
​
        var c = 50;
​
        //【2】创建一个函数
        function fun(){
​
            //(1)操作变量,优先考虑自身作用域内变量
            console.log("c = "+c);   
            console.log("c = "+window.c);
​
            //(2)在函数作用域中也声明一个变量c
            //有以下两种形式
​
            //-1- 使用var关键字声明,声明提前
            // var c =10;  
​
            /*
                在函数中,不使用var声明的变量 ,都会成为全局变量
            */
            //-2- 使用这种方式,不会被声明提前,相当于函数内部没声明过该变量
            c=10;   //变相的修改了全局变量c
​
        }
        //【3】调用函数
        fun();  
​
        //【4】在全局输出c
        console.log("c ="+c);
​
​
        /*
            3-定义形参就相当于在函数作用域中声明了变量
        */
        var e = 3;
        function fun(e){
            console.log("e = "+e);
        }
        fun();
    </script>
</head>
<body>
    
</body>
</html>

声明提前

  • 全局作用域和函数作用域都有声明提前的特性
  1. 变量的声明提前
    1. 使用var 关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)
    2. 但是如果声明变量时不使用var关键字,则变量不会被声明提前
  2. 函数的声明提前
    1. 使用函数声明形式创建的函数创建的函数function 函数(){}
      1. 它会在所有代码执行之前就被创建,所以我们可以在函数声明前来调用函数
    2. 使用函数表达式创建的函数,不会被声明提前,所以不能在函数声明前调用
<!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>Document</title>
    <script>
        /*
            变量的声明提前
                - 使用var 关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值) 
                    但是如果声明变量时不使用var关键字,则变量不会被声明提前
​
​
            函数的声明提前
                - 使用函数声明形式创建的函数创建的函数function 函数(){}
                    它会在所有代码执行之前就被创建,所以我们可以在函数声明前来调用函数
                - 使用函数表达式创建的函数,不会被声明提前,所以不能在函数声明前调用
        */
​
        
        console.log("a = "+a);
        var a ;  //用var关键词声明变量  声明提前
        a = 123;  //赋值不一定提前
        //var a = 123; //该形式域上面两行作用相同
​
        fun();
        fun2();
​
        //函数声明,会被提前创建
        function fun(){    //函数声明方式创建函数
            console.log("我是一个fun 函数");
        }
​
        //函数表达式,不会被提前创建
        var fun2 = function(){
            console.log("我是fun2函数");
        }
​
    </script>
</head>
<body>
    
</body>
</html>

this

  1. 解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数,
    1. 这个隐含的参数就是this,this指向的就是一个对象
    2. 这个对象我们称为函数执行的上下文对象
    3. 根据函数调用方式的不同,this 会指向不同的对象
      1. 以函数的形式调用,this永远都是window
        1. fun()

      2. 以方法的形式调用时,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>Document</title>
    <script>
        function fun(){
            console.log(this);
        }
        //创建一个对象
        var obj = {
            name :"孙悟空",
            sayName: fun
        }
        //以函数形式调用
        fun();
        //以方法的形式调用
        obj.sayName();
        console.log("********");
        /*
            补充
        */
        var name = "全局";
​
        function fun(){
            console.log(name);
            console.log(this.name);
        }
​
        var obj = {
            name : "孙悟空",
            sayName:fun
        }
        var obj2 = {
            name : "沙和尚",
            sayName:fun
        }
        obj.sayName();
        obj2.sayName();
        
        
    </script>
</head>
<body>
    
</body>
</html>

工厂方法创建对象

  • 使用工厂方法创建对象(为将大量重复性代码提取至一个对象或方法中)
    • 通过该方法可以大批量的创建对象
  • 所谓工厂,就是将属性传进去,返回一个对象
<!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>Document</title>
    <script>
        /*
            创建一个对象
        */
        // var obj = {
        //     name:"孙悟空",
        //     age:18,
        //     gender:"男",
        //     sayName:function(){
        //         alert(this.name);
        //     }
        // }
        // obj.sayName();
​
        /*
            使用工厂方法创建对象(为将大量重复性代码提取至一个对象或方法中)
                通过该方法可以大批量的创建对象
            所谓工厂,就是将属性传进去,返回一个对象
        */
       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("至尊宝",18,"男");
       var obj3 =createPerson("孙悟空",18,"男");
       var obj4 =createPerson("白晶晶",18,"女");
       console.log(obj2);
       obj2.sayName();
       console.log(obj3);
       obj3.sayName();
       console.log(obj4);
       obj4.sayName();
​
​
    </script>
</head>
<body>
    
</body>
</html>
  • 使用工厂方法创建的对象,使用的构造函数都是 Object
    • 所以创建的对象都是Object这个类型,就导致我们无法区分出多种不同类型的对象(这种情况考虑下面构造函数的方式来引用对象)

构造函数

创建一个构造函数,专门用来创建不同名称的对象

var per = new Person();

构造函数就是一个普通的函数,创建方式和普通函数没有区别

不同的是构造函数习惯上首字母大写


构造函数的执行流程(系统)

  1. 立即创建一个新的对象
  2. 将新建的对象设置为函数中的this,在构造函数中可以使用this来引用创建的对象
  3. 逐渐执行函数中的代码
  4. 将新建的对象作为返回值返回()
  • 使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类
    • 我们通过一个构造函数创建的对象,称为是该类的实例
  1. 使用 instanceof 可以检查一个对象是否是一个类的实例
    1. 语法:
      1. 对象 instanceof 构造函数
      2. 如果是,返回true,否则返回false
    2. 所有的对象都是Object的后代,
      1. 所以任何对象和Object做instanceof检查时都会反会true。Object类似一个父类

this的情况

  1. 当以函数的形式调用时,this是window,
  2. 当以方法的形式调用时,谁调用方法this就是谁
  3. 当以构造函数的形式调用时,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>构造函数</title>
    <script>
      
        //Person 类
        function Person(name,age,gender){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.sayName=function(){
                alert(this.name);  
            }
        }
        //创建对象 
​
        var per =new Person("至尊宝",18,"男"); 
        var son =new Person("孙悟空",17,"男");
        // console.log(per); 
        // console.log(son); 
        console.log(per instanceof Person);
        
        //Dog 类
        function Dog(name,age,gender){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.sayHello=function(){
                alert("汪汪~~");  
            }
        }
        var dog = new Dog("Harry",3,"雄");
        // console.log(dog);
        // dog.sayHello();
    </script>
</head>
<body>
    
</body>
</html>

构造函数修改

  1. 创建一 个Person构造函数
    1. 在Person构造函数中,为每一个对象都添加了一个sayName方法,
      1. 目前我们的方法是在构造函数内部创建的,
        1. 也就是构造函数每执行一次就会创建一个新的sayName方法
      2. 也是所有实例的sayName都是唯一的。
      3. 这样就导致了构造函数执行一次就会创建一 个新的方法,
        1. 执行10000次就会创建10000个新的方法,而10000个方法都是一摸一样的
        2. 占内存,这是完全没有必要的,完全可以使所有的对象共享同一个方法
  2. 解决方法:
    1. 可以将syaName方法在全局作用域中定义
    2. 但是:
      1. 将函数定义在全局作用域,污染了全局作用域的命名空间
      2. 而且定义在全局作用域中也很不安全

初步修改后练习代码如下:

<!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>构造函数修改版</title>
    <script>
        function Person(name,age,gender){
            this.name = name;
            this.age = age;
            this.gender = gender;
            this.sayName=fun;
        }
​
        //将sayName方法在全局作用域中定义
        function fun(){
            alert("大家好,我是" + this.name);  
        }
​
        var per =new Person("至尊宝",18,"男"); 
        var son =new Person("孙悟空",17,"男");
​
        //检验使用的方法是不是共用的同一个方法
        console.log(per.sayName==son.sayName);
        per.sayName();
        son.sayName();
    </script>
</head>
<body>
    </body>
</body>
</html>

原型对象

原型 prototype

  1. 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
    1. 这个属性对应着一个对象(存有该对象的地址,或者说指向该对象),这个对象就是我们所谓的原型对象
  2. 如果函数作为普通函数调用prototype没有任何作用
  3. 函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性
    1. 指向该构造函数的原型对象,我们可以通过 __proto__ 来访问该属性
  4. 原型对象就相当于一块公共区域,所有同一个类的实例都可以访问到这个原型对象,
  5. 我们可以将对象中共用的内容,统一设置到原型对象中
  6. 当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
    1. 如果没有则会去原型对象中寻找,如果找到则直接使用
  7. 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
    1. 这样不用分别为每一个对象添加, 也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
<!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>原型</title>
    <script>
        /*
            原型 prototype 
            
            我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
                这个属性对应着一个对象(存有该对象的地址,或者说指向该对象),这个对象就是我们所谓的原型对象
​
            如果函数作为普通函数调用prototype没有任何作用
            当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
                指向该构造函数的原型对象,我们可以通过 __proto__ 来访问该属性
            
            原型对象就相当于一块公共区域,所有同一个类的实例都可以访问到这个原型对象,
                我们可以将对象中共用的内容,统一设置到原型对象中
            
            当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
                如果没有则会去原型对象中寻找,如果找到则直接使用
            
            以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
                这样不用分别为每一个对象添加, 也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
​
        */
       function MyClass(name){
            this.name = name;
       }
       
       //向MyClass的原型中添加属性a
       MyClass.prototype.a = 123;
       MyClass.prototype.sayName = function(){
           alert("我是一只"+this.name);
       }
​
       var mc = new MyClass("猫");
       var mc2 = new MyClass("狗");
​
       console.log(MyClass.prototype);
       console.log(mc.__proto__);
       
       //判断MyClass的Prototype属性和MyClass创建的实例对象的隐含属性__proto__指向的是不是同一个对象(原型对象)
       console.log(MyClass.prototype==mc.__proto__);
​
      //判断此时它们的sayName方法是不是共用的同一个
       console.log(mc.sayName==mc2.sayName);
       
    </script>
</head>
<body>
    
</body>
</html>
  • 使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回 true
    • 语法:
    • "属性名" in 对象名
  • 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
    • 使用该方法只有当对象自身中含有属性时,才会返回 true
    • 语法:
      • 对象名.hasOwnProperty("属性名")
    • hasOwnProperty方法在原型对象中
  • 原型对象也是对象,所以它也有原型 ,
    • 当我们使用一个对象的属性或方法时,会先在自身中寻找,
      1. 自身中如果有,则直接使用,
      2. 如果没有则去原型对象中寻找,如果原型对象中有,则使用
      3. 如果没有则去原型的原型中寻找,直到找到Object对象的原型
      4. Object对象的原型没有原型,找到这里还没找到,直接返回undefined
      5. 调取原型对象,如果某级没有原型对象,会返回nullmc.__proto__.__proto__.__proto__ ,返回null时,证明mc对象的原型的原型没有原型对象,或者说原型的值是null,

toString

  • 当我们直接在页面中打印一个对象时,事实上是输出对象的toString()方法的返回值
  • 如果我们希望在输出对象时不输出[object Object], 可以为对象添加一个toString( )方法
<!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>toString</title>
    <script>
​
        function Person(name,age,gender){
            this.name = name;
            this.age = age;
            this.gender = gender;
            
        }
 
        Person.prototype.toString = function(){
            return "Person[name = "+this.name+",age = "+this.age+",gender = "+this.gender+"]";
        }
        var per =new Person("至尊宝",18,"男"); 
​
        //当我们直接在页面中打印一个对象时,事实上是输出对象的toString()方法的返回值
        //如果我们希望在输出对象时不输出[object Object], 可以为对象添加一-个toString( )方法
        // per.toString = function(){
        //     return "Person[name = "+this.name+",age = "+this.age+",gender = "+this.gender+"]";
        // }
​
        console.log(per);
        console.log(per.toString());
        console.log(per.toString()==per);
        
    </script>
</head>
<body>
    
</body>
</html>

垃圾回收(GC)

  1. 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾 这些垃圾积攒过多以后,会导致程序运行的速度过慢,
  2. 所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾 
  3. 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象, 此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
  4.  在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
  5. 我们不需要也不能进行垃圾回收的操作 - 我们需要做的只是要将不再使用的对象设置null即可
<!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>垃圾回收</title>
    <script>
        /*
        垃圾回收(GC)
            - 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
                这些垃圾积攒过多以后,会导致程序运行的速度过慢,
                所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
            - 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
                此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
​
            - 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
                我们不需要也不能进行垃圾回收的操作
            - 我们需要做的只是要将不再使用的对象设置null即可
​
        */
        var obj = new Object();
       
       //想将这个对象回收
       //令这个对象的引用等于0
        obj = null;
        console.log(obj);
    </script>
</head>
<body>
    
</body>
</html>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值