2017-04-01 面向对象学习笔记

闭包复习

  • 闭包概念:
    封闭空间,包裹
  • 闭包的作用:
    延长变量的声明周期
    保护内部的数据,代码更安全
    为我们提供一种间接访问函数内部私有数据的方法
  • 函数内部私有数据的访问
    函数内部声明的变量在函数外部无法访问
    但是有的时候,我们有访问(读取数据 + 修改数据)函数内部私有数据的需求
  • 在函数内部直接返回数据
  • return
    只能获取值,无法修改值
    这种方法获得的数据是一次性的数据,多次获取得到的数据不是同一份
  • 闭包(全世界所有描述 js 的技术文章 32% 在讨论闭包)
    闭包是持有了本来不属于自己数据的函数
<script>
    function demo() {
        var a = 10;
        return a;
    }

    var x = demo();
    var y = demo();
    console.log(x,y);

</script>

<script>
    function demo() {
        var obj = {name:"张三"};
        return obj;
    }

    var o1 = demo();
    var o2 = demo();
    console.log(o1 == o2);

</script>

闭包的基本写法
<script>
    function demo() {
        var n = 10;
        var func = function () {
            return n;
        }
        return func;
    }

    var f1 = demo();
    var x = f1()
    var y = f1();


</script>
<script>
    function demo() {
        var n = {};
        var func = function () {
            return n;
        }
        return func;
    }

    var f1 = demo();
    var x = f1()
    var y = f1();
    console.log(x == y);  //true
</script>

# 闭包的写法01
<script>
    function demo() {
        var n = {};
        var func = function () {
            return n;
        }
        return func;
    }

</script>

# 闭包的写法02
<script>
    function demo() {
        var n = {};
        return function () {
            return n;
        };
    }

    var foo = demo();
    console.log(foo());

</script>

# 闭包的写法03
<script>

    var foo = (function() {
        var n = {};
        return function () {
            return n;
        };
    })();

    var obj1 = foo();
    var obj2 = foo();
    console.log(obj1 == obj2);

</script>

# 访问私有数据(读写)
<script>
    function demo() {
        var a = 10;
        return function (value) {
            if (value != undefined)
            {
                a = value;
            }

            return a;
        }
    }

    var func = demo();
    console.log(func(20));
    console.log(func("这是一个字符串"));
    console.log(func());
    console.log(func(1));
    console.log(func());

</script>

# 返回多个数据 方式一
<script>
    function person() {
        var name = "张三";
        var age = 20;

        return function () {
            return [name,age];
        }
    }

    var foo = person();
    console.log(foo()[0]);
    console.log(foo()[1]);
</script>

# 返回多个数据 方式二
<script>
    function person() {
        var name = "张三";
        var age = 20;

        return [function () {
            return name;
        },function () {
            return age;
        }]
    }

    var foo = person();
    console.log(foo[0]());
    console.log(foo[1]());
</script>

# 返回多个数据 方式三
<script>
    function person() {
        var name = "张三";
        var age = 20;
        return {
            getName:function () {
                return name;
            },
            getAge:function () {
                return age;
            }
        }
    }

    var foo = person();
    console.log(foo.getName());
    console.log(foo.getAge());
</script>

笔试题练习

<script>

    getName();   //3
    function getName() {
        console.log("1");
    }
    getName();  //3
    function Foo() {
        this.getName = function () {
            console.log("2");
        }
    }
    function getName() {
        console.log("3");
    }

    new Foo().getName();

</script>
<script>

    f2();       //报错
    f1();
    f2();       //哈哈

    function f1() {
        function f2() {
            console.log("f2");
        }
    }

    function f2() {
        console.log("哈哈");
    }
</script>

闭包获取和设置数据

<script>
    function demo() {
        var name = "变形记";
        var author = "卡夫卡";
        var price = 12.23;
        var des = "我是一本书";

        function getDes() {
            return des;
        }
        function setDes(value) {
            des = value;
        }

        return {
            getName:function () {
                return name;
            },
            getAuthor:function () {
                return author;
            },
            getPrice:function () {
                return price;
            },
            setName:function (value) {
                if (value != undefined)
                {
                    name = value;
                }
            },
            setAuthor:function (value) {
                if (value != undefined)
                {
                    author = value;
                }
            },
            setPrice:function (value) {
                if (value != undefined)
                {
                    price = value;
                }
            },
            getDes:getDes,
            setDes:setDes
        }
    }

    var func = demo();
    console.log(func.getName());
    console.log(func.getAuthor());
    console.log(func.getPrice());

//    console.log(func.getName("城堡"));  //设置
//    console.log(func.getName());
    func.setName("城堡");
    console.log(func.getName());
    func.setPrice(30.00);
    console.log(func.getPrice());

    console.log(func.getDes());
</script>

闭包的作用

  • 延长变量的声明周期
  • 保护内部的数据,代码更安全,做一些数据检验处理
  • 为我们提供一种间接访问函数内部私有数据的方法
<script>
   var foo =  (function () {
       var name = "张三";
       var age = 20;

       return {
           getName:function () {
               return name;
           },
           getAge:function () {
               return age;
           },
           setName:function (value) {
               name = value;
           },
           setAge:function (value) {
               //检验
               if (value < 0)
               {
                   value = 0;
               }
               age = value
           }
       }
    })();

   console.log(foo.getName());
    foo.setName("李四");
   console.log(foo.getName());

//    var name = "sss";
//    var name = "123";
   console.log(foo.getAge());
   foo.setAge(-2);
   console.log(foo.getAge());

</script>

<script>
    function demo() {
        var a = 10;
    }

    demo();
    demo();
</script>

setTimeOut 和闭包的执行

  • 定时器
    setTimeOut(只执行一次)
    setInterval(每个一段时间执行一次)
<script>
    var date = new Date();
    console.log(date);
    setTimeout(function () {
        console.log("定时器" + new Date);
    },2000)
</script>
  • 思考
    js 代码的执行

  • 页面渲染任务

  • js 主要代码 (for,语句)

  • 事件型的任务(点击事件,定时器事件)

  • js 本身是单线程的

  • 进程:系统中正在运行的运行程序,是 cpu 调度的单位,是分配资源的最小单位

  • 线程:进程中真正执行任务的部分,是 CPU 调度的最小单位, CPU 不会为线程分配资源

  • 关系:包含关系(进程包含线程),一个进程可以拥有多个线程,至少要有一条线程(主线程 - UI 线程)

  • 进程(正在运行的学校)

  • 线程(老师)

  • 线程执行任务的时候是串行执行:一条线程在执行多个任务的时候是按照任务的固定顺序一个接着一个的执行

  • 多线程:一个进程可以拥有多个线程,多条线程在执行任务的时候并发(行)执行

  • 多线程的并发执行:多条线程执行多个任务,多个任务一起执行,给人感觉在同时执行

  • 并发和秉性的区别
    并发:多个任务同时执行(现象)
    并行:能力

   for (var i = 0; i < 10; i++) {
//        setTimeout((function (j) {
//            return function () {
//                    console.log("定时器" + new Date +j );
//            }
//        })(i),0);

        (function (j) {
            setTimeout(function () {
                console.log("定时器" + new Date +j );
            },0);
        })(i);
    }

div 事件和闭包

<body>
<div>第1个标签</div>
<div>第2个标签</div>
<div>第3个标签</div>
<div>第4个标签</div>
<div>第5个标签</div>
<div>第6个标签</div>

<script>
    //01 获得页面中所有的div标签
    var divs = document.getElementsByTagName("div");

    for (var i = 0; i < divs.length; i++) {
//        divs[i].onclick = (function (j) {
//           return function () {
//                alert("第" + j + "个标签");
//            }
//        })(i);

        (function (j) {
            divs[j].onclick = function () {
                alert("第" + j + "个标签");
            }
        })(i)
    }
</script>
</body>

函数补充说明

  • 函数的几种创建方式
  • 函数声明 function 名称(参数1,参数2){函数体}
  • 函数表达式
    var 变量1 = functon 名称(参数1,参数2){函数体} 命名函数表达式
    var 变量2 = function(参数1,参数2){函数体} 匿名函数表达式
  • 使用构造函数来创建
    var func = new Function()
 var func01 = function name() {
        console.log("func01");
    }

    var func02 = function () {
        console.log("func02");
    }

    //细微的差别:name(函数名称)
    //函数本身是对象,函数有属性(name)
    console.log(func01.name);     //name
    console.log(func02.name);     //空  谷歌浏览器打印的结果是func02

    func01.des = "des";
    console.log(func01.des);

    var obj = {
        name:"张三",
        showName:function () {
            console.log(this.name);
        }
    }

    delete obj.showName;
    obj.showName();


//    function demo() {
//        var a = 10;
//        var b = 20;
//    }
//
//
//    {
//        var a = 10;
//        var b = 20;
//    }
//
//    函数:函数是有名字的代码块。
//    demo();
//    demo();
//    demo();

函数的回调

  • 函数回调:函数作为其他函数的参数来使用。
  • 需要注意 this 的指向
  function foo(callBack,callBackObj) {
        //............

        if (typeof callBack == "string")
        {
            callBack = callBackObj[callBack]
        }

        callBack.call(callBackObj);    //以普通函数方式调用  this(window)
    }

    function demo() {
        console.log("demo");
    }

    foo(demo);

    var dog = {
        color:"红色",
        age:0.3,
        showAge:function () {
            console.log(this.age);
        }
    }
    foo(dog.showAge,dog);

    var person = {
        color:"红色",
        age:99,
        showAge:function () {
            console.log(this.age);
        }
    }
    foo(person.showAge,person);

    foo("showAge",person);   //兼容性处理

函数作为返回值(计数器)

   function demo() {
        var count = 0;
        return function () {
            return count ++;
        }
    }

    var next = demo();
    console.log(next());  //0
    console.log(next());
    console.log(next());
    console.log(next());
    console.log(next());

自定义函数(惰性函数定义)

  • 自定义函数(惰性函数定义)
    特点:函数的内容在第二次调用的时候才被正确的定义,第一次调用的时候主要做一些初始化处理 + 更新函数
  • 使用的场景:
    代码需要做一些一次性的初始化处理
  function foo() {
        console.log("foo!");
        //初始化操作......
        foo = function () {
            console.log("foo! foo!");

            foo = function () {
                console.log("foo! foo! foo!");
            }
        }
    }

    foo(); // foo!
    foo(); // foo! foo!
    foo(); // foo! foo! foo!
  • 使用注意:
  • 添加在函数对象上面的成员会丢失
  • 如果把函数赋值给变量或者是称为对象的方法,那么再调用的时候还是执行旧的函数体
  function demo() {
        console.log("1");
       demo = function () {
           console.log("2");
       }
    }

    demo.des = "描述信息";
    console.log(demo.des);
//    demo();
    console.log(demo.des);

    //01 赋值给变量

//    var func = demo;
//    func();  //1
//    func();  //1
//    func();  //1
//    demo();  //2

    //01 赋值给对象
    var o = {};
    o.desLog = demo;
    o.desLog();
    o.desLog();
    o.desLog();
    demo();

即时对象初始化

  ({
        name:"张安",
        age:23,
        showName:function () {
            console.log(this.name);
        },
        showAge:function () {
            console.log(this.age);
        },
        init:function (nameValue,ageValue) {
            //需要进行初始化处理的代码
            //...............
            this.name = nameValue;
            this.age = ageValue;
            this.showName();
            this.showAge();
        }
    }).init("隔壁老王","23");

即时函数补充

  • 即时函数的组成
  • 函数 function (形参){函数体}
  • ()把函数包裹起来
  • ()马上调用并执行函数
  //01
    (function () {
        console.log("我要过节啦,好开心啊");
    })();

    //02
    (function () {
        console.log("我要过节啦,好开心啊");
    }());

    //03 非主流的写法
    !function () {
        console.log("我要过节啦,好开心啊");
    }();
    +function () {
        console.log("我要过节啦,好开心啊");
    }();

    -function () {
        console.log("我要过节啦,好开心啊");
    }();

    ~function () {
        console.log("我要过节啦,好开心啊");
    }();

  • 即时函数可以接收参数也可以有返回值
  var a = 10;
    var result = (function (n) {
        return n + 1;
    })(a);

    console.log(result);

笔试题练习

  • 穿件对象的几种方法
  • 字面量
  • 内置构造函数
  • 工厂函数
  • 自定义构造函数
# 01 以下创建对象的方法,错误的是:
<script>
    var obj1 = new Object();
    obj1.name = "XMG";
    obj1.getName = function () {
        return this.name;
    }
    console.log(obj1.getName());
</script>
<script>
    var obj2 = {
        name:"XMG",
        getName:function () {
            return this.name;
        }
    }

    console.log(obj2.getName());
</script>
<script>
   var MYClass = function () {
        this.name = "XMG";
        this.getName = function () {
            return this.name;
        }
    };

    var obj3 = new MYClass();
    console.log(obj3.getName());
</script>
<!--<script>-->
    <!--var obj4;               //undefined-->
    <!--obj4.name = "XMG";-->
    <!--obj4.getName = function () {-->
        <!--return this.name;-->
    <!--};-->
    <!--console.log(obj4);-->
<!--</script>-->


函数和变量声明的提升(函数和变量同名)
# 02 请给出以下代码的打印结果
<script>
    console.log(test);            //函数
    function test() {};
    console.log(typeof test);   //function?string

    var test = "2017";
    console.log(test);            //2017

</script>







# 03 请给出以下代码的输出结果
<!--<script>-->
    <!--var f = new Number(true);  //仅仅为1的时候|true-->
    <!--if (f == true) {-->
        <!--var a = 10;-->
    <!--}-->

    <!--function fn() {-->
        <!--var b = 20;-->
        <!--c = 30;-->
    <!--}-->

    <!--fn();-->
<!--//    console.log(a);  //?  10 ? undefined  ?报错-->
<!--//    console.log(b);  //?   报错-->
    <!--console.log(c);   //30-->

<!--</script>-->

<!--# 04 请给出下面代码的输出结果-->
<!--<script>-->

    <!--var str1 = new String("demo01");-->
    <!--var str2 = new String("demo01");-->
    <!--var str3 = "demo01";-->
    <!--console.log("undefined" == undefined);  //不相等-->
    <!--console.log("+++");-->

    <!--console.log(str1 == str2);  //false-->
    <!--console.log(str1 == str3);  //true-->
    <!--var name = 'World!';-->

    <!--(function () {-->
        <!--//"undefined" == undefined  相等比较(如果类型不一样那么会隐式转换)-->
        <!--if (typeof name == undefined) {-->
            <!--var name = '文顶顶';-->
            <!--console.log('Goodbye ' + name);-->
        <!--} else {-->
            <!--console.log('Hello ' + name);-->
        <!--}-->
    <!--})();-->

<!--</script>-->

<!--#05 请给出下面代码的结果-->
<!--<script>-->
    <!--console.log(Array.isArray(Array.prototype));-->
<!--</script>-->

#06 请给出下面代码的输出结果
<!--<script>-->

    <!--//[0] == true false-->
    <!--//[1] == true true-->
    <!--//数组 在比较的时候只有内容是1的时候为true-->
    <!--//if判断的时候 [0] [1] [] {}都为真 -->
    <!--// 对象和布尔类型(true|false)比较永远都为false-->
    <!--//几种结果:true false NO-->
    <!--var a = [];-->
    <!--if (a) {-->
        <!--console.log([1] == true);    //false-->
    <!--} else {-->
        <!--console.log("NO");-->
    <!--}-->

    <!--console.log("___");-->
<!--</script>-->

#07 请给出下面代码的输出结果
<script>
    (function(){
        var x = y = 1;

        //y = 1;
        //var x = 1;

    })();

    console.log(y); //能够获取y的值吗?
    console.log(x); //能够获取x的值吗?

笔试题2

  • 考察
    prototype 和proto
    构造函数.prototype
    对象.proto
    注意:
    对象.prototype 和 对象.proto_ 不是一回事
    对象.prototype 指的是访问对象的 prototype 属性
    如果该对象是一个普通的对象(非构造函数),那么不存在该属性
    对象.proto 指的是访问创建该对象的构造函数的原型对象,等价于 构造函数.prototype
# 01 请给出下面代码的输出
<script>
    var a = {};
    var b = Object.prototype;
    console.log(a.__proto__ == Object.prototype);  //true
    console.log(a.prototype === b);    //false

    console.log(Object.getPrototypeOf(a) === b);  //true ? false

</script>

#02 请给出下面代码的输出结果
<!--<script>-->

    <!--function f() {}-->
    <!--var a = f.prototype;-->
    <!--var b = Object.getPrototypeOf(f);   //f.__proto__ = Function.prototype = 空函数-->
    <!--console.log(a === b);-->
    <!--console.log("++++");-->
<!--//    console.log(a,b);-->

    <!--console.log(b == f);-->

<!--</script>-->

<!--#03 请给出输出结果-->
<script>

    function foo() { }
    var oldName = foo.name;
    foo.name = "bar";   //函数设置name属性没有作用

    console.log(oldName);  //undefined ==》foo
    console.log(foo.name); //bar       ==> foo

        console.log(oldName === foo.name);
//    console.log([oldName, foo.name]);
</script>

#04 请给出输出结果
<script>

    function f() {}
    var parent = Object.getPrototypeOf(f);  //f.__proto__ =》Function.prototype (空函数)

    console.log(f.name);                    // ?
    console.log(parent.name);               // ?

    //A "f", "Empty"  正确
    //B "f", undefined

设计模式的简单说明

  • 设计模式
    解决软件开发中的常见应用场景所采取的不同套路
    常见的设计模式:23种
  • 分类
    创建型的模式
    行为型的模式
    常用:单利模式 + 工厂模式 + 观察者模式 + 策略模式 + 代理模式 + 享元模式 + 桥接模式
    推荐:大话设计模式(大话数据结构)
    其主要是架构师工作
  • 起源
    建筑行业(哥特风格 中式风格)
    Gof 四人组

工厂函数创建对象

 function createPerson(name,age) {
        var o = new Object();
        o.name = name;
        o.age = age;
        return o;
    }

    var p1 = createPerson("张三",20);

工厂函数简单说明

  • 工厂模式
    核心过程
  • 提供一个父构造函数
  • 设置父构造函数的原型对象(方法)
  • 在父构造函数身上添加静态工厂方法
  • 定制合作伙伴(创建子构造函数)
  • 使用工厂函数来创建对象
//01 提供一个父构造函数
    function MakePhone() {}
    //02 设置父构造函数的原型对象(方法)
    MakePhone.prototype.desLog = function () {
        console.log("我们的口号是:" + this.des);
    }

    //03 在父构造函数身上添加静态的工厂方法
    MakePhone.factory = function (type) {
        //001 接受参数,并做容错性处理
        var typeString = type;
        if (typeString == undefined) {
            throw "请选择厂商";
        }
        //002 判断是否支持生产
        if (typeof MakePhone[typeString] != "function") {
            throw "不支持该手机厂商!";
        }

        //MakePhone.oppo  ==》当做构造函数来使用
        //003 设置继承
        MakePhone[typeString].prototype = MakePhone.prototype;   //获得原型对象上面的方法
        //004 创建产品
        var newPhone = new MakePhone[typeString]();
        return newPhone;
    }

    //04 定制合作伙伴(设置子构造函数)
    MakePhone.oppo = function () {
        this.des = "充电两小时,通话五分钟";
    }
    MakePhone.vivo = function () {
        this.des = "照亮你的美,啊哈哈哈哈";
    }
    MakePhone.zuimei = function () {
        this.des = "你的青春我做主";
    }

    // 05 使用工厂函数来创建对象
    var oppo = MakePhone.factory("oppo");
    oppo.desLog();
    var vivo = MakePhone.factory("vivo");
    vivo.desLog();
    var zuimei = MakePhone.factory("zuimei");
    zuimei.desLog();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 单例模式 适用场景:可能会在场景中使用到对象,但只有一个实例,加载时并不主动创建,需要时才创建 最常见的单例模式,...
    Obeing阅读 2,053评论 1 10
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,716评论 2 17
  • 一、JavaScript基础知识回顾 1.1 JavaScript 1.1.1 javascript是什么? Ja...
    福尔摩鸡阅读 1,224评论 0 7
  • 函数的调用方式和 this 丢失 函数调用方式 普通函数方式调用 this - window 对象的...
    GodlinE阅读 219评论 0 1
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,585评论 18 139