JavaScript 面向对象、构造函数部分

目录

回顾面向对象的概念

认识面向对象

构造函数

工厂模式

prototype  原型对象

混合法——构造函数

原型详解

继承和多态

继承

多态

ECMA6-class语法

面向对象实战和this指向问题

拖拽继承版和选项卡改造

继承拖拽——实现限制出界

选项卡——面向对象改造


回顾面向对象的概念

认识面向对象

见 认识对象内容

构造函数

工厂模式

  1. 原料
  2. 加工
  3. 出厂

【注】凡是满足上述三个步骤创建对象的函数,我们把它叫做工厂方法

        function createPerson(name, sex){
            //1、声明空对象
            var obj = new Object();
            //2、加工
            obj.name = name;
            obj.sex = sex;
            obj.showName = function(){
                alert("我的名字叫" + this.name);
            }
            obj.showSex = function(){
                alert("我的性别是:" + this.sex)
            }
            //3、出厂
            return obj;
        }
        var p1 = createPerson("blue", "男");
        p1.showName();
        p1.showSex();

        var p2 = createPerson("red","女");
        p2.showName();
        p2.showSex();

如果我们某一个函数,使用new运算符去调用:

        1、当前函数中的this指向新创建的对象

        2、自动去完成1.原料和3.出场操作

这种通过new调用函数,我们把它叫做构造函数,构造函数可以构造对象

【注】构造函数一般情况下首字母大写

    function Person(name, sex){
            this.name = name;
            this.sex = sex;
            this.showName = function(){
                alert("我的名字叫" + this.name);
            }
            this.showSex = function(){
                alert("我的性别是:" + this.sex)
            }
        }
        var p1 = new Person("blue", "男");
        p1.showName();
        p1.showSex();

        var p2 = new Person("red","女");
        p2.showName();
        p2.showSex();
        alert(p1.showName === p2.showName); //false

prototype  原型对象

概念:每一个函数上,都有一个原型对象prototype 

/* 想要给数组添加一个方法,可以对数组中每一个元素进行求和 */
        var arr1 = [1, 2, 3, 4, 5];
        var arr2 = [1, 2, 3, 4, 5];
        arr1.sum = function(){
            var res = 0;
            for(var i = 0; i < this.length; i++){
                res += this[i];
            }
            return res;
        }

        arr2.sum = function(){
            var res = 0;
            for(var i = 0; i < this.length; i++){
                res += this[i];
            }
            return res;
        }

        alert(arr1.sum());
        alert(arr2.sum());

        alert(arr1.sum == arr2.sum);//false;arr1.sum和arr2.sum是两个函数,尽管他们的代码相同

用在构造函数上,我们可以给构造函数的原型prototype添加方法:

1、如果我们将方法添加到构造函数的原型prototype对象上

2、构造函数构造出来的对象共享原型上所有的方法

    var arr1 = [10, 20, 30, 40, 50];
        var arr2 = [1, 2, 3, 4, 5];

        Array.prototype.sum = function(){
            var res = 0;
            for(var i = 0; i < this.length; i++){
                res += this[i];
            }
            return res;
        }

        alert(arr1.sum());
        alert(arr2.sum());
        alert(arr1.sum == arr2.sum);//true

混合法——构造函数

    function Person(name, sex){
            this.name = name;
            this.sex = sex;
        }

        //Person构造函数添加方法,添加在构造函数的原型上prototype
        Person.prototype.showName = function(){
            alert("我的名字叫" + this.name);
            
        }
        Person.prototype.showSex = function(){
            alert("我的性别是:" + this.sex)
            
        }

        var p1 = new Person("blue", "男");
        p1.showName();
        p1.showSex();

        var p2 = new Person("red","女");
        p2.showName();
        p2.showSex();
        alert(p1.showName === p2.showName); //true

原型详解

构造函数构造出来的对象,有一个属性 __proto__ ,指向构造出这个对象的构造函数的原型

instanceof  关键字

        功能:判断某一个对象是否是这个构造函数构造出来的

    function Dog({name, type, age}){
            //添加属性
            this.name = name;
            this.type = type;
            this.age = age;
        }

        /* 通过构造函数的原型添加方法 */
        Dog.prototype = {
            run: function(){
                alert(this.name + "会飞快的奔跑");
            },
            showSelf: function(){
                alert(`这是一个${this.type}的,${this.age}岁的,叫${this.name}的小狗`)
            }
        }

        var xiaobai = new Dog({
            name: "小白",
            type: "比熊",
            age: 3
        });
        alert(xiaobai.__proto__ == Dog.prototype);//true

        alert(xiaobai instanceof Dog);  //true
        alert(xiaobai instanceof Object);  //true

        var xiaohei = new Dog({
            name: "小黑",
            type: "拉布拉多",
            age: 5
        });
        alert(xiaohei.__proto__ == Dog.prototype);//true

继承和多态

面向对象,继承,封装(封装构造函数过程),多态

继承

        分类更加细分的构造函数

原型链继承

    function Dog({name, type, age}){
            //添加属性
            this.name = name;
            this.type = type;
            this.age = age;
        }

        /* 通过构造函数的原型添加方法 */
        Dog.prototype = {
            run: function(){
                alert(this.name + "会飞快的奔跑");
            },
            showSelf: function(){
                alert(`这是一个${this.type}的,${this.age}岁的,叫${this.name}的小狗`)
            }
        }

        function Teddy({name, type, age, color}){
            //1、继承父一级构造函数所有的属性
            //构造函数的伪装
            Dog.call(this,{
                name: name,
                type: type,
                age: age
            })
            //添加自己的属性
            this.color = color;
        }

        var xiaohong = new Teddy({
            name: "小花",
            type: '泰迪',
            age: 10,
            color: "红色"
        })

        alert(xiaohong.name);
        alert(xiaohong.type);

多态

只会在子一级生效,并不会影响父一级构造函数的方法。

继承和多态是同一件事情的两种完全不同的侧重:

继承:侧重是从父一级构造函数,继承到的属性和方法(和父亲一样的地方)

多态:侧重是,子一级,自己重写和新增的属性和方法(和父亲不一样的地方)

面向对象是一个编程思想,支撑面向对象编程思想的语法是类(ECCMA6之前没有类这个概念)和对象,构造函数充当类的角色。

构造函数和对象实现面向对象程序的时候,体现出多态

ECMA6-class语法

   function Person(name, sex, age){
            this.name = name;
            this.sex = sex;
            this.age = age;
        }
        Person.prototype.showSelf = function(){
            alert(`我是一个叫${this.name},今年${this.age}岁的${this.sex}孩`);
        }

        //白领人
        function Worker(name, sex, age, job){
            //1、构造函数的伪装 —— 继承父级的属性
            Person.call(this, name, sex, age);
            this.job = job;
        }
        //2、原型链  继承父一级的方法
        //<1>通过for...in遍历继承
        /* for(var funcName in Person.prototype){
            Worker.prototype[funcName] = Person.prototype[funcName];
        } */
        //<2>Object.create( )
        /* Worker.prototype = Object.create(Person.prototype); */
        //<3>调用构造函数继承
        Worker.prototype = new Person();
        Worker.prototype.showJob = function(){
            alert("我的工作是:" + this.job);
        }

        var w1 = new Worker("小米","男",20,"程序员");
        w1.showSelf();
        w1.showJob();

-----------------------------------------------------------------------------------------

         /* ECMA6  class语法 */
        class Person{
            //class属性添加
            constructor(name, sex, age){
                this.name = name;
                this.sex = sex;
                this.age = age;
            }
            showSelf(){
                alert(`我是一个叫${this.name}的,今年${this.age}岁的${this.sex}孩`);
            }
        }

        var p1 = new Person("blue","男",18);
        p1.showSelf();

        //extends 继承
        class Worker extends Person{
            constructor(name, sex, age, job){
                //1、继承到父一级的属性
                super(name, sex, age);
                this.job = job;
            }
            showJob(){
                alert("我的工作是" + this.job);
            }
        }

        var w1 = new Worker("小米","男",20,"程序员");
        w1.showSelf();
        w1.showJob();

面向对象实战和this指向问题

        /* 
            this指向当前函数的主人。
            总结this容易混乱的部分:
                1、事件绑定
                2、定时器
        */

        function Aaa(){
            this.a = 10;
            var oBtn = document.getElementById("btn1");
            var _this = this;
            // //赋值
            // oBtn.onclick = function(){
            //     _this.show();
            // }

            // oBtn.onclick = this.show.bind(this);

            //传参 等于 赋值
            // setTimeout(this.show.bind(this),4000);

            setTimeout(function(){
                _this.show();
            },4000);
        }

        Aaa.prototype.show = function(){
            alert(this.a);
        }

        window.onload = function(){
            var a1 = new Aaa();
            a1.show();
        }
        // var oDiv = null;
        // var offsetX = 0;
        // var offsetY = 0;


        function Drag(id){
            this.oDiv = document.getElementById(id);
            var _this = this;
            this.oDiv.onmousedown = function(ev){ 
                _this.funcDown(ev);
            };
            document.onmouseup = this.funcUp;
        }

        Drag.prototype.funcDown = function(ev){
            var e = ev || window.event;
            this.offsetX = e.clientX - this.oDiv.offsetLeft;
            this.offsetY = e.clientY - this.oDiv.offsetTop;

            var _this = this;
            document.onmousemove = function(ev){
                _this.funcMove(ev);
            };
        }

        Drag.prototype.funcMove = function(ev){
            var e = ev || window.event;
            this.oDiv.style.left = e.clientX - this.offsetX + 'px';
            this.oDiv.style.top = e.clientY - this.offsetY + 'px';
        }
        Drag.prototype.funcUp = function(){
            document.onmousemove = null;
        }

        window.onload = function(){
            new Drag("div1");    
        }

可以将上述函数封装在.js中,调用的时候会非常方便                                                 

拖拽继承版和选项卡改造

继承拖拽——实现限制出界

function Drag(id){
    this.oDiv = document.getElementById(id);
    var _this = this;
    this.oDiv.onmousedown = function(ev){ 
        _this.funcDown(ev);
    };
    document.onmouseup = this.funcUp;
}

Drag.prototype.funcDown = function(ev){
    var e = ev || window.event;
    this.offsetX = e.clientX - this.oDiv.offsetLeft;
    this.offsetY = e.clientY - this.oDiv.offsetTop;

    var _this = this;
    document.onmousemove = function(ev){
        _this.funcMove(ev);
    };
}

Drag.prototype.funcMove = function(ev){
    var e = ev || window.event;
    this.oDiv.style.left = e.clientX - this.offsetX + 'px';
    this.oDiv.style.top = e.clientY - this.offsetY + 'px';
}
Drag.prototype.funcUp = function(){
    document.onmousemove = null;
}
/* 
    限制出界的拖拽,要拥有拖拽原有的所有功能
*/
function LimitDrag(id){
    //继承父一级所有的属性  构造函数的伪装
    Drag.apply(this, [id]);
}

//继承方法  原型链
for(var funcName in Drag.prototype){
    LimitDrag.prototype[funcName] = Drag.prototype[funcName];
}

LimitDrag.prototype.funcMove = function (ev){
    var e = ev || window.event;
    var l = e.clientX - this.offsetX;
    var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
    if(l <= 0){
        l = 0;
    }
    if(l >= windowWidth - this.oDiv.offsetWidth){
        l = windowWidth - this.oDiv.offsetWidth;
    }
    var t = e.clientY - this.offsetY;
    var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
    if(t <= 0){
        t = 0;
    }
    if(t >= windowHeight - this.oDiv.offsetHeight){
        t = windowHeight - this.oDiv.offsetHeight;
    }
    this.oDiv.style.left = l + 'px';
    this.oDiv.style.top = t + 'px';
}
<!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>
    <style>
        #div1{width: 200px; height: 200px; background-color: red; position: absolute;}
        #div2{width: 100px; height: 100px; background-color: orange; position: absolute; left: 500px;}
    </style>
    <script src="drag.js"></script>
    <script src="LimitDrag.js"></script>
    <script>
        window.onload = function(){
            new Drag("div1");    
            new LimitDrag("div2");
        }
    </script>
</head>
<body>
    <div id="div1"></div>
    <div id="div2"></div>
</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>
    <style>
        #div1 button{width: 100px; height: 30px; background-color: gray; color: white; font-size: 18px;}
        #div1 .active{background-color: orange; color: blue;}
        #div1 div{width: 340px; height: 300px; border: 1px solid black; display: none;}
    </style>
    <script>
        function TabSwitch(id){
            //添加属性
            var node = document.getElementById(id);
            this.aBtns = node.getElementsByTagName("button");
            this.aDivs = node.getElementsByTagName("div");

            var _this = this;

            //将点击按钮,进行切换得方法添加给每一个按钮
            for(var i = 0; i < this.aBtns.length; i++){
                //找到当前按钮下标
                this.aBtns[i].index = i;
                this.aBtns[i].onclick = function(){
                    _this.tab(this);
                };
            }
        }

        /* //添加方法
        TabSwitch.prototype.tab = function(oBtn){
            //清楚页面上所有按钮和所有div的样式
            for(var i = 0; i < this.aBtns.length; i++){
                this.aBtns[i].className = '';
                this.aDivs[i].style.display = 'none';
            }
            //获取当前点击的按钮
            oBtn.className = 'active';
            this.aDivs[oBtn.index].style.display = 'block';
        } */

        //添加方法
        TabSwitch.prototype.tab = function(_this){
            //清楚页面上所有按钮和所有div的样式
            for(var i = 0; i < this.aBtns.length; i++){
                this.aBtns[i].className = '';
                this.aDivs[i].style.display = 'none';
            }
            //获取当前点击的按钮
            _this.className = 'active';
            this.aDivs[_this.index].style.display = 'block';
        }

        window.onload = function(){
            new TabSwitch("div1");
        }
    </script>
</head>
<body>
    <div id="div1">
        <button class="active">HTML5</button>
        <button>Python</button>
        <button>Java</button>
        <div style="display: block;">HTML5是Web中核心语言HTML的规范,用户使用任何手段进行网页浏览时看到的内容原本都是HTML格式的。在浏览器中通过一些技术处理将其转换成了课识别的信息。HTML5在从前HTML4.01的基础上进行了一定的改进,虽然技术人员再开发过程中可能不会将这些新技术投入应用,但是对于该种技术的新特性网站开发技术人员是必须要有所了解的。</div>
        <div>Python是一种计算机程序设计语言。是一种面向对象的动态类型语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的、大型项目的开发。</div>
        <div>Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念。因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好的实现了面向对象理论,允许程序员以优雅的思维方式进行复杂的编程</div>
        
    </div>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值