zoukankan      html  css  js  c++  java
  • js两种定义函数、继承方式及区别

    一:js两种定义函数的方式及区别

    • 1:函数声明:
    function  sayA() {   alert("i am A");  }
    
    • 2:函数表达式:
    var sayB = function() {   alert("i am B");  }
    
    前者会在代码执行之前提前加载到作用域中,后者则是在代码执行到那一行的时候才会有定义

    二:js两种继承方式及区别

    • 对象冒充
      • 临时属性
      • call()
      • apply()
    • 原型链 code
    • 继承应选哪种 code

    三:实例

    js两种定义函数的方式:

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
    <title>js两种定义函数的方式</title>
    <script language="javascript">
        say(); 
        var say =function(){
            alert("567");
        }
        function say(){
            alert("123");
        }  
    </script>
    </head>
    <body>
    </body>
    </html>
    //在javascript函数体内(执行作用域)声明的变量,无论在函数体何处声明,它将都会被提升到函数的顶部,我们称这种现象为变量提升。 
    函数呢,它也有这种特性,即无论在函数体何处声明另一个函数,它将都会被提升到函数的顶部。
    只是采用函数表达式和函数声明所体现的函数提升的内容是有差别的:函数表达式和变量提升类似,只会提升函数的变量,不提升函数的定义;
    而函数声明提升时,不仅仅会提升函数的声明,函数的定义也会被提升
    

    对象冒充:临时属性

    function Person(name){
         this.name = name;
         this.say = function(){
            alert('My name is '+this.name);
         }
    }
    function Student(name,id){
        this.temp = Person;
        this.temp(name); 
        delete this.temp;
        this.id = id; 
        this.showId = function(){
           alert('Good morning,Sir,My student number is '+this.id);
        }
    }
    var simon = new Student('Simon',9527);
    simon.say(); //my name id simon
    simon.showId(); //Good morning,Sir,My work number is 9527
    

    对象冒充:apply()/call():

    function Person(name){
        this.name = name;
        this.say = function(){
          alert('My name is '+this.name);
        }
    }
    function Student(name,id){
         Person.call(this,name); //apply():Person.apply(this,new Array(name));
         this.id = id;
         this.showId = function(){
            alert('Good morning,Sir,My student number is '+this.id);
         }
    }
    var simon = new Student('Simon',9527);
    simon.say();
    simon.showId();
    //apply(this,arguments):方法能劫持另外一个对象的方法,继承另外一个对象的属性. 
                            arguments:是一个数组,new Array(name,age)等
    //call(id,name,age)
    //什么情况下用apply,什么情况下用call  
    在给对象参数的情况下,如果参数的形式是数组的时候,
    比如apply示例里面传递了参数arguments,这个参数是数组类型,
    并且在调用Person的时候参数的列表是对应一致的(也就是Person
    和Student的参数列表前两位是一致的) 就可以采用 apply , 
    如果我的Person的参数列表是这样的(age,name),而Student
    的参数列表是(name,age,grade),这样就可以用call来实现了,
    也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));  
    //apply和call中的参数顺序以父类为准。
    

    原型链继承:new

    var Shape = function(width, height) {
        this.width = width;
        this.height = height;
    };
    Shape.prototype.area = function() {
        return this.width * this.height
    };
    var shape = new Shape(20, 30);
    shape.area();
    > 600
    

    原型链继承:无new

    function Shape(width, height) {
        if (!(this instanceof Shape)) {
            return new Shape(width, height);
        }
        this.width = width;
        this.height = height;
        return this;
    }   
    Shape.prototype.area = function() {
        return this.width * this.height
    };
    var shape = Shape(20, 30);
    console.log(shape.area());
    

    选择最优继承方式:

    1:在OO概念中,new实例化后,对象就在堆内存中形成了自己的空间, 值得注意的是,这个代码段。而成员方法就是存在这个代码段的, 并且方法是共用的。问题就在这里,通过对象冒充方式继承时, 所有的成员方法都是指向this的,也就是说new之后,每个实例将 都会拥有这个成员方法,并不是共用的,这就造成了大量的内存浪费。 并且通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法,如以下代码将会出错:

    function Person(name){
        this.name = name;
        this.say = function(){
           alert('My name is '+this.name);
        }
    }
    Person.prototype.age = 20;
    Person.prototype.sayAge = function(){alert('My age is '+this.age)};
    function Student(name,id){
         Person.apply(this,new Array(name));
             this.id = id;
             this.showId = function(){
             alert('Good morning,Sir,My student number is '+this.id);
         }
    }
    
    var simon = new Student('Simon',9527);
    simon.sayAge(); //提示TypeError: simon.sayAge is not a function   
    

    2:原型链方式继承,就是实例化子类时不能将参数传给父类,这个例子中function Person()没有参数。

    function Person(name){
        this.name = name;
    }
    Person.prototype.say = function(){
        alert('My name is '+this.name);
    }
    function Student(name,id){
        this.id = id;
        this.showId = function(){
           alert('Good morning,Sir,My student number is '+this.id);
     }
    }
    Student.prototype = new Person();
    //此处无法进行传值,this.name或者name都不行,
    //直接写Student.prototype = new Person('wood')是可以的,
    //但是这样的话simon.say()就变成了My name is wood
    var simon = new Student("Simon",9527);
    simon.say();  //弹出 My name is undefined
    simon.showId(); 
    

    结论:

    成员变量采用对象冒充方式,成员方法采用原型链方式
    
    function Person(name){
        this.name = name;
    }
    Person.prototype.say = function(){
        alert('My name is '+this.name);
    }
    function Student(name,id){
        Person.call(this,name);
        this.id = id;
    }
    Student.prototype = new Person(); 
    //此处注意一个细节,showId不能写在Student.prototype = new Person();前面
    Student.prototype.showId = function(){
        alert('Good morning,Sir,My student number is '+this.id);
    }
    var simon = new Student("Simon",9527);
    simon.say();
    simon.showId();
  • 相关阅读:
    第10组 Beta冲刺 (3/5)
    第10组 Beta冲刺 (2/5)
    第10组 Beta冲刺 (1/5)
    第10组 Alpha冲刺 (3/6)
    第10组 Alpha冲刺 (2/6)
    第10组 Alpha冲刺 (1/6)
    第一次作业
    第二次作业
    机器学习_第一次个人作业
    软工实践个人总结
  • 原文地址:https://www.cnblogs.com/m-xy/p/3924355.html
Copyright © 2011-2022 走看看