2017-03-31 面向对象学习笔记

2017-03-31  本文已影响0人  GodlinE

函数的调用方式和 this 丢失

var name = 'window 的属性';
function demo(){
        console.log(this.name);
}
var obj = {
        name:"张三",
        demo:demo
}
demo();
obj.demo();
var div = document.getElementById('demoId');
console.log(div);
//var div2 = getId('demoId');
//console.log(div2);
//document.getElemenetById 方法内部的实现,在该方法内部使用到了 this
//这个 this 默认指向的是document
//getId 在调用的时候使用普通函数的方式来进行调用, this 指向的是 window
document.getId = document.getElemenetById;
var div3 = document.getId('demoId');
console.log(div3);
//console.log(document.getElemenetById.call(document,''demoId));
//getId('demo');
var getId = (function(){
        return function(){
                  //return document.getElementById.call(document,arguments[0]);
                  return document.getElemenetById.apply(document,arguments);
        }
})();
var div4 = getId('demoId');
console.log(div4);

图书管理员面向对象

//注意点:在原型对象的方法中访问该对象的其他方法,需要使用 this 前缀
function BookListManager(){
         this.bookList = null;
}
BookListManager.prototype = {
        constructor:BookListManager,
        init:function(){
                this.bookList = arr || [];
        },
        getBook:function(name){
                for(var i in this.bookList){
                          if(this.bookList[i].name == name){
                                return this.bookList[i];
                          }
                  }
                  throw "要查找的对象不存在!"
        },
        updateBook:function(name,author){
                //先找到这个对象
                var book = this.getBook(name);
                //修改对象
                book.author = author;
        },
        addBook:function(obj){
                this.bookList.push(obj);
        },
        removeBook:function(){
                var book = this.getBook(name);
                var index = this.bookList.indexOf(book);
                if(index == -1){
                        throw '要删除的对象不存在'
                }
                //删除该对象
             this.bookList.splice(index,1);
        }
}
var jack = new BookListManager();
var tom = new BookListManager();
jack.init([{name:'古典文学研究',author:'古典'},{name:'莫言文集',author:'莫言'}]);
jack.addBook({name:'飞鸟集',author:'泰戈尔'});
console.log(jack.getBook('飞鸟集'));
jack.updateBook('飞鸟集','老太太');
jack.removeBook('飞鸟集');
console.log(jack.bookList);

严格模式的简单说明

严格模式使用注意

    "use strict";

    //01 在严格模式下,所有的变量都必须使用var声明
    //   在默认情况下,如果不适用var声明变量,那么该变量默认会成为window的属性(全局变量)
//    var a = 10;
//    b = 20;
//    console.log(b);

    //02 在严格模式下,禁止使用八进制
//    var num = 022;            //数值以0开头,以八进制的方式来处理
//    var num = 0x22;
//    console.log(num);

    //03 在严格模式下,禁止使用使用with
//    var obj = {name:"张三",age:20};
//    with (obj)
//    {
//        name = "李四";
//        age = 99
//    }
//    console.log(obj);

    //04 在严格模式下, 不能删除全局的变量
    //   在默认情况下,可以删除全局变量(不能删除成功),静默失败
//    var str = "string";
//    console.log(delete str);
//    console.log(str);

    //05 在严格模式下,不能在if语句中声明函数
//    if (true)
//    {
//        function demo() {
//            console.log("demo");
//        }
//
//        demo();
//    }

    //06 在严格模式下,函数的形参不能出现同名的情况
//    function test(a,b,a) {
////        var a = 1;
////        var b = 2;
////        var a = 3;
//        console.log(a + b + a);   //6 ? 8 ? 4  后面的会把前面的覆盖
//    }
//
//    test(1,2,3);

    //07 在严格模式下,不能使用arguments.callee|caller
    //caller 指向的函数的调用者 注意点:window调用该函数,指向的是null
    //arguments.callee 常用在递归调用中,指向的是函数自己
//    function f1() {
//        f2();
//    }
//    function f2() {
//        console.log(f2.caller);
//    }
//    f1();
//    f2();

//    console.log((function (n) {
//    if (n == 1) {
//        return 1;
//    }
//
//    return arguments.callee(n - 1) + n;
//})(11));

    //08 在严格模式下, 不能使用eval和arguments作为标识符(变量和函数的名称)
//    var eval = "测试字符串";
//    console.log(eval);
//    var arguments ="....";
//    console.log(arguments);

    //09 在严格模式下,修正了this的指向
    //   默认情况下,this指向的是window,严格模式指向的undefined
//    function func() {
//        console.log(this);
//    }
//
//    func();
//    var o = {};
//    func.call(null);            //严格模式下,指向的是null
//10 在严格模式下,arguments的表现不一致
    //在默认情况下,如果函数内部形参被重新设置,那么arguments也会跟着改变
    //在严格模式情况下,如果函数内部形参被重新设置,那么arguments不会被改变,他们是相互独立的
    //值类型的数据作为函数的参数
    function demo(str) {
        console.log(str);
        console.log(arguments[0]);


        //重新设置形参的值
        str = "hahahaha";
        console.log(str);
        console.log(arguments[0]);
    }
    demo("123456");

    //引用类型的数据作为函数参数
    function demo(obj) {
        console.log(obj);
        console.log(arguments[0]);

        //重新设置形参的值
        obj = {age:20};
        console.log(obj);
        console.log(arguments[0]);
    }
    demo({name:"张三"});

严格模式的书写格式

//"use strict";
//"use strict"               正确
//'use strict';     正确
//'use strict'      正确
//use strict;       错误
//"use Strict";     错误
//"use  strict";    错误
//"use strict ";    错误
//" use strict";      错误

严格模式的作用范围

//    "use strict";    //位置01  对整个作用域中的代码都有用

   function demo01() {
//       "use strict";    //位置02   仅仅对当前的函数有用,函数后面的代码不受影响
       a = 10;
       console.log(a);
   }

   function demo02() {
//       "use strict";    //位置03  仅仅对当前的函数有用
       b = 20;
       console.log(b);
   }

   demo01();
   demo02();

作用域说明

  var a = "test-A";
    function f1() {
        var b = "test-B";

    }
    
    function f2() {
        var c = "test-C";
    }

  for (var i = 0; i < 10; i++) {
        console.log(i);
    }

    console.log(i,"_____");             //? 10

    try
    {
        //可能出错的代码
        a();
    }catch (error){
        //如果出错了,那么就执行此处的代码
        console.log(error);
    }
//    console.log(error);
  var demo = "测试的字符串01";
    function f1() {
        var demo = "demo";
        var test = 10;
        f2();
    }

    function f2() {
        console.log(demo);
        console.log(test);
    }

//    f2();   //测试的字符串
    f1();   //demo

变量和函数的提升

  console.log("_____");
    console.log(a);            //und
    var a = "test-A";
    console.log(a);            //Test-A
    var a = "demo-A";
    console.log(a);            //demo-A

    //模拟变量声明的提升
//    var a;
//    console.log("_____");
//    console.log(a);            //und
//    a = "test-A";
//    console.log(a);            //Test-A
//    a = "demo-A";
//    console.log(a);            //demo-A
</script>
<script>

    f1();                      //Demo
    function f1() {
        console.log("Test");
    }
    f1();                      //Demo
    function f1() {
        console.log("Demo");
    }
    f1();                       //Demo



    //模拟提升
//    function f1() {
//        console.log("Demo");
//    }
//    f1();                      //Demo
//    f1();                      //Demo
//    f1();
</script>

<!--<script>-->
    <!--console.log(a);                    //函数-->
    <!--var a = "test-A";-->
    <!--function a() {-->
        <!--console.log("demo-A");-->
    <!--}-->
    <!--console.log(a);                   //函数-->



    <!--//模拟-->
    <!--var a;-->
    <!--function a() {-->
        <!--console.log("demo-A");-->
    <!--}-->
    <!---->
    <!--console.log(a);                    //函数-->
    <!--a = "test-A";-->
    <!--console.log(a);                   //test-A-->
<!--</script>-->

<script>
    console.log(a);
    var a = "test-A";
    function a() {
        console.log("demo-A");
    }

//    不管函数在前面还是变量在前面,打印出来的结果都是函数
</script>

思考:
<script>
    var demoA ="10";
    function foo() {
        console.log(demoA);            //10  undefined(正确)
        var demoA = "20";
        console.log(demoA);            //20
    }

    function func() {
        console.log(demoA);            //10
        demoA = "30";
        console.log(demoA);           //30
    }

    foo();
    func();

    console.log(demoA);                 //30

变量提升是分作用域的


    console.log(demo);
    var a = "第一个a";
    function demo() {
        console.log(a);   //? undefined
        a = "张三";
        console.log(a);   //张三
        var a = "哈哈哈";
        console.log(a);   //哈哈哈
    }

    console.log(a);
    demo();
    console.log(a);     //第一个a(正确) ? 张三  ?哈哈哈
</script>

<script>
    var b = 10;
    function test() {
        console.log(b);
        var b = 20;
    }

    console.log(b);    //10
    test();            //und
    console.log(b);
</script>

函数表达式的提升

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

<script>
//    var func02;
    console.log(func02);;
    var func02 = function () {
        console.log("func02");
    }
</script>

笔试题练习

<script>
    function foo() {
        var num = 123;
        console.log(num);  //123
    }
    foo();
    //console.log(num);       //报错

</script>

<script>
    var scope = "global";
    foo();
    function foo() {
        console.log(scope);  //?global
        scope = "local";
        console.log(scope);  //?local
    }

    console.log(scope);         //local
</script>

in:检查对象中是否存在指定的属性
<!--<script>-->
    <!--function f1(){-->
        <!--var a;-->
        <!--if("a" in window){-->
            <!--a = 10;-->
        <!--}-->
        <!--console.log(a); //? 10 ? undefined ?报错-->
    <!--}-->

    <!--f1();-->

<!--</script>-->

<!--<script>-->
    <!--if("a" in window){-->
        <!--var a = 10;-->
    <!--}-->
    <!--console.log(a); //?  10 -->
<!--</script>-->

<!--<script>-->
    <!--if(!"a" in window){-->
        <!--var a = 10;-->
    <!--}-->
    <!--console.log(a); //?-->
<!--</script>-->



<script>
    if("a" in window){
      a = 10;
    }
    console.log(a); //?  报错
</script>

<script>
    var foo = 1;
    function bar() {
        var foo;
        if(!foo)
        {
            foo = 10;
        }
        console.log(foo);   //?
    }
    bar();
//    undefined == null;  相等
//    undefined == false;  不相等
//    !undefined
    console.log(undefined === null);   //true
    console.log(!undefined == true);
</script>

  function Foo() {
        getName = function(){
            console.log("1");
        };
        return this;
    }
    Foo.getName = function() {
        console.log("2");};
    Foo.prototype.getName = function(){
        console.log("3");};
    var getName = function() {
        console.log("4");
    };
    function getName(){
        console.log("5");
    }
    Foo.getName();      // ? 2
    getName();          // ? 4
    Foo().getName();        // ? (1) ? 3 ? 2 ? 4
    getName();              // ? (1)
    new Foo.getName();      // ? 2
    new Foo().getName();    // ? 3
    new new Foo().getName(); // ? 3

作用域链

  var a = "a";
    //f1--->全局作用域
    function f1() {
        var b = "b";
        var a = "f1-a"
        //f2-->f1--->全局作用域
        function f2() {
            var c = "c";
            var b = "f2--b";
            //f3-->f2-->f1--->全局作用域
            function f3() {
                var d = "d";

                //f4-->f3-->f2-->f1--->全局作用域
                function f4() {
                    console.log(a, b, c, d,e);
                }

                f4();

            }
            f3();
        }
        f2();
    }

    f1();

作用域链绘图

// f4();
}

function f3() {
}
f2();
上一篇下一篇

猜你喜欢

热点阅读