大前端

JavaScript实现继承的4类方式

2017-01-06  本文已影响65人  oldSix_Zhu

若有不妥,请多指教
目录:
-1.JavaScript实现继承的4类方式
-2.JavaScript是一门'解释执行'的脚本语言


1.JavaScript实现继承的4类方式

先白话一下JavaScript为什么实现继承有那么多种方式,不像OC直接搞个类继承就可以了
什么是对象
--生活中的对象就是实物,一辆车,一台手机,一个人
--对象具有特征(属性)和行为(方法)
什么是面向对象
--可以创建自定义的类型,很好的支持继承和多态.(即创建类)
面向对象的语言很多,OC,swift,java,C++...
--面向对象的特征:封装,继承,多态
--万物皆对象:世间的一切事物都可以用对象来描述
什么是基于对象
--无法创建自定义的类型,不能很好的支持继承和多态.
JS就是基于对象的.
JS的继承是指一个对象可以使用另一对象的属性与方法

1.1原型继承
1.1.1

  <script>
       //《JavaScript语言精粹》作者提出了一个方式来实现继承
       function jicheng(obj){
           var o = {};
           o.__proto__ = obj;
           return o;
       }

       var obj1= jicheng({name:"邱淑贞"});
       console.log(obj1);
  </script>

1.1.2

<script>
    //原型继承
    //利用原型中的成员可以被和其相关的对象共享这一特性,可以实现继承
    //这种实现继承的方式,就叫做原型继承
    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    //给原型对象中添加属性或者方法(通过对象的动态特性)
    //不是严格意义上的继承
    Person.prototype.say = function () {
        console.log("爱你呦");
    }
    Person.prototype.beauty = 100;

    //这里的p对象就继承原型
    var p = new Person("邱淑贞",18);
    p.say();//爱你呦
    console.log(p.beauty);//100

    //2.还可以直接替换原型对象
    var star = {
        say : function () {
            console.log("超级爱你呦");
        }
    }
    Person.prototype = star;
    var p2 = new Person("王祖贤",18);
    p2.say();//超级爱你呦
</script>

1.1.3

<script>
    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    Person.prototype.say = function () {
        console.log("爱你呦");
    }
    //直接替换原型对象方法
    //旧的原型中方法被覆盖了
    var star = {
        say : function () {
            console.log("超级爱你呦");
        }
    }
    Person.prototype = star;
    var p2 = new Person("王祖贤",18);
    p2.say();//超级爱你呦
</script>

1.2混入式继承

    <script>
      var obj1 = {
            name :"爸爸",
            age : 40,
            sayHello :function () {
                console.log("Hello world");
            }
        }
        var obj2 = {

        }

        //混入式继承
        for(var k  in obj1){
            obj2[k] = obj1[k];
        }
        console.log(obj2);//打印Object
    </script>

一般这么写:

  <script>
        // 实现混入的函数
        function extend(o1, o2) {
            for ( var key in o2 ) {
                o1[key] = o2[key];
            }
        }
        // 构造函数Fn
        function Fn() {}
        // 给Fn默认的原型中混入字面量对象的value属性,
        // 这样Fn.prototype里也有了value属性。
        extend(Fn.prototype, {
            value: 100
        });
        // 通过Fn创建一个obj实例
        var obj = new Fn();
        // 因为实例继承Fn.prototype,所以可以使用value属性
        console.log(obj.value);//打印100
  </script>

1.3经典继承Object.create()

  <script>
        //经典继承的语法
        //Object.create(obj)
        //返回值为一个对象,继承自参数中的obj
        //这个方法是ES5中出来的,所以存在兼容性问题,所以一般不用
        var obj1 = {
            name:"邱淑贞"
        };
        var obj2 = Object.create(obj1);
        console.log(obj2.name);//邱淑贞
  </script>

不过也有处理的方法:

  <script>
        //如何处理Object.create的兼容性问题
        var obj = {
            name:"邱淑贞"
        };

        //检测浏览器的能力,如果没有Object.create方法就给他添加一个(不推荐使用)
        if(Object.create){
            var o = Object.create(obj);
        }else{
            Object.create = function () {
                function F() {
                }
                F.prototype = obj;
                var o = new F();
            }
            var o = Object.create(obj);
        }

        //自己定义个函数
        function create(obj){
            if(Object.create){
                return Object.create(obj);
            }else{
                function F() {
                }
                F.prototype = obj;
                return new F();
            }
        }
  </script>

1.4构造函数实现继承
不懂可以看下我的这篇文章:<a href="http://www.jianshu.com/p/a888f53c0906">JS函数的4种调用模式</a>

  <script>
        function Person(){
            this.name = "邱淑贞";
            this.age = 18;
        }

        function Star(){
            var star = this;
            Person.apply(star);
        }

        var star = new Star();
        console.log(star);
  </script>

3.JavaScript是一门'解释执行'的脚本语言

如果我们将这段js代码放在<head>中,它将无法实现点击button换图片的功能,console出现爆红:

<head>
  <script type="text/javascript">
    var img1 = document.getElementsByClassName('icon')[0];
    function changeImage() {
        img1.src = 'images/2.JPG';
    }
  </script>
</head>
<body>
  ![](images/1.jgp)
  <button onclick="changeImage();">更改图片</button>
</body>

而如果我们把js代码拿到<body>中最下面,又能实现这个功能了:

<head>

</head>
<body>
  ![](images/1.jgp)
  <button onclick="changeImage();">更改图片</button>
  <script type="text/javascript">
    var img1 = document.getElementsByClassName('icon')[0];
    function changeImage() {
        img1.src = 'images/2.JPG';
    }
  </script>
</body>

这就是'解释执行'的意思了,从上到下依次执行.
所以在第1份代码中拿到的img1为空,因为还没走到body中创建img;
第2份代码中body中已经创建好了img,所以即使不在方法中也可以拿到img1.

关于'解释执行'和'编译执行'整理了一下:
计算机有个编译器是将一种语言转换成另一种语言(一般是机器语言)的东西,我们的编译执行类语言走这个机器;
还有个解释器是执行一种语言的东西,解释执行语言走这个机器;
解释器编译器可以为语言提供更高的复杂度,但执行效率不如编译器,二者背后的最大区别是:对解释执行而言,程序运行时的控制权在解释器而不在用户程序;对编译执行而言,运行时的控制权在用户程序;
解释具有良好的[动态特性]和[可移植性]比如在解释执行时可以动态改变变量的类型、对程序进行修改以及在程序中插入良好的调试诊断信息等,而将解释器移植到不同的系统上,则程序不用改动就可以在移植了解释器的系统上运行。(这也就是JavaScript作为一种解释性脚本语言可以在浏览器上做抢火车票插件的原因)
同时解释器也有很大的缺点,比如执行效率低,占用空间大,因为不仅要给用户程序分配空间,解释器本身也占用了宝贵的系统资源

上一篇下一篇

猜你喜欢

热点阅读