3

1.对象

  1. 对象的定义 : 对象 是 由 键值对 组成的无序集合。
  2. 创建对象两种方法 :
    方法一 : 字面量方法

       var obj = {name: "k"};

    方法二 : new Object( ) 构造函数创建

       var a = new Object();
       a.name = "zm";
       console.log( a ); // {name: "zm"}
    

2.面向对象和面向过程的比较

如果 想要把大象放进冰箱。

1.面向过程思想的逻辑思维是:

1.打开冰箱
2.把大象放入冰箱
3.关上冰箱

解析: 面向过程思想的逻辑思维是,我们先做什么,然后做什么,最后做什么。是分步骤一步一步往下走。

疑问:?️也许有许多小伙伴觉得,面向过程很符合我们的思维逻辑啊。的确如此,但是面向过程的缺点是扩展性和复用性很差。如果我们想要:
把狮子放入冰箱

1.打开冰箱
2.拿出大象
2.把狮子放入冰箱
3.关上冰箱

把老虎放入冰箱

1.打开冰箱
2.拿出狮子
2.把老虎放入冰箱
3.关上冰箱

2.面向对象思想的逻辑思维是:

    冰箱:
        打开
        关上
        清空            
        
    动物: 
        进入   

3.批量创建对象

1.通过调用函数创建对象。

<script>
    //函数作用:创建一个对象,带有name和age属性,say方法。
    function createObj( name,age ){
        var o={};//创建一个新的对象
        o.name=name;//为对象添加属性
        o.age=age;//为对象添加属性
        o.say = function(){//为对象添加方法
            console.log( "我是人" );
        };
        return o;
    }

    var obj = createObj("kimoo",28);
    console.log( obj );//{name: "kimoo", age: 28, say: ƒ}

    var obj2 = createObj("zm",38);
    console.log( obj2 );//{name: "zm", age: 38, say: ƒ}

    console.log(obj.say===obj2.say);//false
</script>

解析: say 方法,每次调用函数都会生成一个新的对象,会生成新的say( )方法。所以,每次调用createObj( name,age ); ,都会生成新的say( )方法,但是每个say方法的功能都一样,这样对性能有影响。

2.通过调用函数创建对象,性能优化。

<script>
//    批量创建对象
    var obj = createObj("kimoo",28); 
    console.log( obj );
    obj.say();
    
    var obj2 = createObj("zm",38); 
    console.log( obj2 );
    obj2.say();
    
    console.log( obj.say === obj2.say ); // true
    
    function say(){
        console.log( "我是人" );
    }
    
    function createObj( name,age ){
        var o = {};
        o.name = name;
        o.age = age;
        o.say = say;
        return o;
    }
</script>

3.函数的比较

        var fn1 = function(){
            alert(1);
        };
        var fn2 = function(){
            alert(1);
        };
        console.log( fn1 === fn2 ); // false
//---------------------------------------------------
        var temp = function(){alert(2)};
        var fn3 = temp;
        var fn4 = temp;
        console.log( fn3 === fn4 );// true

解释:无论如何定义一个函数,JS解释器都会把它翻译成一个Function对象。所以每次创建一个自定义函数,都会创建一个新的对象。例如:fn1和 fn2变量都是存储对象的地址,虽然创建新对象的内容是一样的,但是在浏览器解析的时候,它会给对象创建一个地址。fn1和fn2存储的地址不相等,故fn1和fn2不相等。 fn3存储是temp接受的对象的地址,fn4存储也是temp接受的对象的地址。故fn3和fn4不相等。

4.构造函数

情况一:没有返回值,打印的是undefined。

<script>
    function fn(){
        console.log( 1 );
    }

    var res1 = fn();
    console.log( res1 );//undefined

解析:当函数没有返回值的时候,将函数调用赋给变量,打印的值是undefined。因为没有返回值。

情况二:使用 new 来调用函数,没有返回值,打印的是{}(空对象)。

    使用 new 来调用函数
            函数内部会自动return 一个对象
        如果函数内部使用了 return X
            如果 X 是一个 非null 的 对象res
                那么通过new 调用 ,返回的是 res
            
            如果 X 是 非对象 或者 null
                那么通过new 调用 ,返回的是 {}            

举例说明:

<script>
    function fn(){
        console.log( 1 );
//        return 2;//当return的值是2,console.log( res2 )打印结果是{}
//        return null;//当return的值是null,console.log( res2 )打印结果是{}
//        return {b:3};//当return的值是{b:3},console.log( res2 )打印结果是{b:3}
    }

    var res2 = new fn();
    console.log( typeof res2 );//object
    console.log( res2 );
</script>

进一步对情况二说明:使用 new 来调用函数的过程

使用 new 来调用函数
第一步:函数内部会自动为我们创建一个对象
第二步函数内部的 this 指向会变为 当前构造函数生成的对象
第三步:会自动return

<script>
    function fn(name, age){
//第一步        var obj = {};
        console.log( this );//第二步:这个this指向的是生成的对象res。打印结果是:fn{}
        this.name = name;
        this.age = age;
    }
//    fn();  //如果是这样直接调用,指向的是windows。
    
    var res = new fn("kimoo",28);
//        此处: 通过new 调用fn ,
//            fn 被称为 构造函数
//            res 是 fn 的 实例
//            整个过程 被称为 实例化
            
    console.log( res ); //fn {name: "kimoo", age: 28}
</script>

5.通过构造函数批量创建对象

约定: 构造函数的大驼峰写法

<script>
    function CreatePerson( name,age ){
        this.name = name;
        this.age = age;
        this.say = function(){
            console.log( "我是人");
        }
    }
    
    var p1 = new CreatePerson("kimoo",28);
    console.log( p1 );//{name: "kimoo", age: 28, say: ƒ}
    p1.say();//我是人
    
    var p2 = new CreatePerson("zm",38);
    console.log( p2 );//{name: "zm", age: 38, say: ƒ}
    p2.say();//我是人
    console.log( p1.say === p2.say ); //false 性能上的浪费:方法并没有共享。为解决这个问题,除了上面把函数提取出来的方法,可以使用prototype。
</script>

6.prototype 原型

prototype (原型):当一个函数被申明的时候,该函数下默认有一个属性:prototype,该属性的值是一个对象。

<script>
    function CreatePreson(){}
    console.dir( CreatePreson );
</script>

结果为:

图片描述

当我们去调用一个对象的属性或者方法的时候,
如果该对象自身没有该属性或方法,则会调用到该对象 的 构造函数的prototype的属性或方法

把通过构造函数构造出来的对象,共有的方法或者属性,放在prototype身上,能够达到性能节约的办法。

<script>
    function CreatePreson(){
    }
    CreatePreson.prototype.say = function(){console.log(1);};
    CreatePreson.prototype.name = "k";

    var p = new CreatePreson();
    p.say();// 当我们去调用一个对象的属性或者方法的时候,自身没有的时候,找构造函数的prototype的属性或者方法
    console.log( p.name ); // 当我们去调用一个对象的属性或者方法的时候,自身没有的时候,找构造函数的prototype的属性或者方法

    var p2 = new CreatePreson();
    p2.say();// 当我们去调用一个对象的属性或者方法的时候,自身没有的时候,找构造函数的prototype的属性或者方法
    console.log( p2.name ); // 当我们去调用一个对象的属性或者方法的时候,自身没有的时候,找构造函数的prototype的属性或者方法

    console.log( p.say === p2.say );//true
    
    
</script>

7.__proto__

__proto__
    当一个对象被创建的时候,该对象会自动被添加上一个属性:__proto__,他的值也是一个对象,并且该属性 就是 当前这个对象的构造函数的prototype
    对象.__proto__ === 构造函数.prototype
<script>
    function CreatePreson(){};
    var p1 = new CreatePreson();
    console.log( CreatePreson.prototype === p1.__proto__ );//true

8.选项卡(用面向对象的思想写一遍)

查看选项卡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="box"></div>
<script>
    function CraetTab(param) {
        this.el = param.el;
        this.buttonText = param.buttonText;//button按钮的内容
        this.contentText = param.contentText;//div的内容
        this.button = [];//生成button元素用button数组存储
        this.content = [];//生成div元素用div数组存储
        this.current = 0;//记录当前显示的button和div
        this.autoPlay = param.autoPlay!==undefined?param.autoPlay:true;//默认自动播放
    }
    CraetTab.prototype.init=function () {
        //生成对应style样式
        var style=document.createElement("style");
        style.innerHTML="#"+this.el.id+" .active{background-color: red;}#"+this.el.id+" .show{display: block;}#"+this.el.id+" div{display: none;}";
        document.body.appendChild(style);

        //根据创建对象的buttonText个数生成button
        //并把每一个生成的button塞入数组中
        //将生成的button添加到box中
        for(var i=0;i<this.buttonText.length;i++){
            var btu=document.createElement("button");
            btu.innerHTML=this.buttonText[i];
            this.button.push(btu);
            this.el.appendChild(btu);
        }

        //根据创建对象的contentText个数生成div
        //并把每一个生成的div塞入数组中
        //将生成的div添加到box中
        for(var i=0;i<this.contentText.length;i++){//生成div
            var div=document.createElement("div");
            div.innerHTML=this.contentText[i];
            this.content.push(div);
            this.el.appendChild(div);
        }

        //如果this.autoPlay为真,则开启定时器,让选项卡自动播放
        if(this.autoPlay){
            var num=0;
            var that=this;//由于在setInterval事件中this就指的是当前的window。所以要在外部存储指向对象的this。
            setInterval(function () {
                for(var i=0;i<that.buttonText.length;i++){
                    that.button[i].classList.remove("active");
                    that.content[i].classList.remove("show");
                }
                that.button[num].classList.add("active");
                that.content[num].classList.add("show");
                num++;
                num%=that.buttonText.length;
            },1000)
        }
        this.setCss();
        this.addEvent();
    };
    
    //大清洗,给当前显示的div和button添加样式
    CraetTab.prototype.setCss=function () {
        for(var i=0;i<this.buttonText.length;i++){
            this.button[i].classList.remove("active");
            this.content[i].classList.remove("show");
        }
        this.button[this.current].classList.add("active");
        this.content[this.current].classList.add("show");

    };
    //给button添加点击事件,点击哪个就将that.current的值改成对应button的索引值。
    CraetTab.prototype.addEvent=function () {
        var that=this;//由于在button点击事件中this就指的是当前的button。所以要在外部存储指向对象的this。
        for(var i=0;i<this.buttonText.length;i++){
            this.button[i].index=i;
             this.button[i].onclick=function () {
                 that.current= this.index;
                 that.setCss();
             }
        }
    };
    var box=document.getElementById("box");
    var t1 =new CraetTab({
        el: box,
        buttonText: [
            "按钮1",
            "按钮2",
            "按钮3"
        ],
        contentText:[
            "内容1",
            "内容2",
            "内容3"
        ],
        autoPlay:false
    });
    t1.init();
</script>
</body>
</html>

梁志芳
159 声望58 粉丝

正在学习CSS+HTML+JS