1.立即执行函数 return 与 window的区别

1.window写法new Foo.getName

  1. ;(function(){
  2. var Test = function(){
  3. console.log('123');
  4. }
  5. Test.prototype = {
  6. }
  7. window.Test = Test;
  8. })();
  9. Test();
  10. Test()只执行时执行一次

2.return 写法

  1. var Test = (function(){
  2. var Test = function(){
  3. console.log('345');
  4. }
  5. return Test;
  6. })();
  7. Test();
  8. Test() 执行两次

2.三目运算

  1. var str = 89>9 ? (
  2. '89'>'9'?'通过了':'内层未通过'
  3. )
  4. : '外层未通过';
  5. console.log(str);

3.浅拷贝: 浅拷贝就是将对象中的所有元素复制到新的对象中

浅拷贝对于原始值类型与引用类型的方式有区别
1.原始值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值
2.引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象
在副本中对子元素引用类型的字段值被修改后,源对象的值也将被修改。

  1. Object.prototype.num = 1;
  2. var person1 = {
  3. name:'张三',
  4. age:18,
  5. sex:'male',
  6. height:180,
  7. weight:140,
  8. son:{
  9. first:'Jenney',
  10. second:'Lucy',
  11. Third:'Jone'
  12. },
  13. children:{
  14. first:{
  15. name:'张小一',
  16. age:13
  17. },
  18. second:{
  19. name:'张小二',
  20. age:14
  21. },
  22. third:{
  23. name:'张小三',
  24. age:15
  25. },
  26. },
  27. car:['Benz','Mazda']
  28. }
  29. var person2 = {};
  30. for(var key in person1){
  31. person2[key] = person1[key];
  32. }
  33. person2.name = '李四';
  34. person2.son.forth = 'Ben';
  35. console.log(person1,person2);
  36. //此方法原型链上的属性也会复制到新对象中 num:1

image.png

浅拷贝封装函数 排查原型链上继承的属性

  1. Object.prototype.num = 1;
  2. var person1 = {
  3. name:'张三',
  4. age:18,
  5. sex:'male',
  6. height:180,
  7. weight:140,
  8. son:{
  9. first:'Jenney',
  10. second:'Lucy',
  11. Third:'Jone'
  12. },
  13. children:{
  14. first:{
  15. name:'张小一',
  16. age:13
  17. },
  18. second:{
  19. name:'张小二',
  20. age:14
  21. },
  22. third:{
  23. name:'张小三',
  24. age:15
  25. },
  26. },
  27. car:['Benz','Mazda']
  28. }
  29. var person2 = clone(person1);
  30. function clone(origin,target){
  31. var target = target || {}
  32. for(var key in origin){
  33. //筛选origin对象自身的属性
  34. if(origin.hasOwnProperty(key))
  35. target[key] = origin[key];
  36. }
  37. return target;
  38. }
  39. person2.name = '李四';
  40. person2.son.forth = 'Ben';
  41. console.log(person1,person2);
  42. //副本更改源数据也会更改

image.png

4.深拷贝

深拷贝和上面浅拷贝不同,就是彻底copy一个对象,而不是copy对象的引用。

方法一: 原生写法

         Object.prototype.num = 1;
        var person1 = {
            name:'张三',
            age:18,
            sex:'male',
            height:180,
            weight:140,
            son:{
                first:'Jenney',
                second:'Lucy',
                Third:'Jone'
            },
            children:{
                first:{
                    name:'张小一',
                    age:13
                },
                second:{
                    name:'张小二',
                    age:14
                },
                third:{
                    name:'张小三',
                    age:15
                },
            },
            car:['Benz','Mazda']
        }
                var person2 = deepClone(person1);
        person2.name = '李四';
        person2.children.forth = {
            name:'张小四',
            age:1
        };
        person2.car.push('BYD');
        console.log(person1,person2);
        function deepClone(origin,target){
            var target = target || {},
                toStr = Object.prototype.toString,
                arrType = '[object Array]';
            for(var key in origin){
                if(origin.hasOwnProperty(key)){
                    if(typeof(origin[key]) === 'object' && origin[key] !== null){  // 先测是否是引用型 typeof([]) 等于 object
                        // if(toStr.call(origin[key]) === arrType){
                        //     target[key] = [];
                        // }else{
                        //     target[key] = {};
                        // }
                        target[key] =  toStr.call(origin[key]) === arrType ? [] : {};
                        deepClone(origin[key],target[key]); //递归执行
                    }else{
                        target[key] = origin[key];
                    }
                }
            }
            return target;
        }

image.png

方法二:通过JSON方法 弊端不能拷贝对象里的方法

        Object.prototype.num = 1;
        var person1 = {
            name:'张三',
            age:18,
            sex:'male',
            height:180,
            weight:140,
            son:{
                first:'Jenney',
                second:'Lucy',
                Third:'Jone'
            },
            children:{
                first:{
                    name:'张小一',
                    age:13
                },
                second:{
                    name:'张小二',
                    age:14
                },
                third:{
                    name:'张小三',
                    age:15
                },
            },
            car:['Benz','Mazda']
        }
                var str = JSON.stringify(person1);
        var person2 = JSON.parse(str);
        person2.name = '李四';
        person2.children.forth = {
            name:'张小四',
            age:1
        };
        person2.car.push('BYD');
        console.log(person1,person2);

习题

1

        function test(){
            console.log(foo); //undefined
            var foo = 2;
            console.log(foo); //2
            console.log(a); //报错 
        }
        test();

2.

        function a(){
            var test;
            test();
            function test(){
                console.log(1); //1
            }
        }
        a();
        // AO = {
        //     test: undefined => test(){}
        // }

3.

        var name = '222'
        var a ={
            name :'111',
            say:function(){
                console.log(this.name);
            }
        }
        var fun = a.say;
        fun(); // 2222
        a.say(); // 111
        var b = {
            name:'333',
            say:function(fun){
                fun();
            }
        }
        b.say(a.say); // 2222
        b.say = a.say; 
        b.say()// 333

image.png

4.

        function test(){
            var marty = {
                name:'marty',
                printName:function(){
                    console.log(this.name);
                }
            }
            var test1 = {
                name: 'test1'
            }
            var test2 = {
                name: 'test2'
            }
            var test3 = {
                name:'test3',
                printName:function(){
                    console.log(this.name);
                }
            }
            test3.printName = marty.printName;
            marty.printName.call(test1);    // test1  this的指向被改成 test1
            marty.printName.apply(test2); // test2 this的指向被改成 test2
            marty.printName(); //marty
            test3.printName(); //test3
        }
        test();

5.

        var bar = {
            a:'1'
        };
        function test(){
            bar.a = 'a';
            Object.prototype.b='b';
            return function inner(){
                console.log(bar.a); // a
                console.log(bar.b); // b 自身没有的属性去上级寻找
            }
        }
        console.log(test());
        test()();

image.png

课后作业

1.写出代码的执行结果跟步骤

        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(); 
        getName();
        Foo().getName();
        new Foo.getName();
        new Foo().getName();
        new new Foo().getName()

解析: Foo.getName();
函数也是特殊的对象 所以 Foo.getName() 等价于=> 执行 function Foo(){} 这个函数对象下面的getName属性 Foo.getName = function(){
console.log(2);
}
所以输出2
getName();
GO:{
getName: 1.undefined => 2. function getName(){ 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
}
所以输出4;
Foo().getName();
执行 function Foo(){ 因为 getName 没有 var 所以变量提升到全局
getName = function(){
console.log(1);
}
return this;
}
所以 GO:{
getName: 1.undefined => 2. function getName(){ => 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
4. getName = function(){
console.log(1);
}
}
所以输出1
getName();
GO:{
getName: 1.undefined => 2. function getName(){ => 3.赋值操作 var getName = function(){
console.log(5); console.log(4);
} }
4. getName = function(){
console.log(1);
}
}
所以还是输出1
new Foo.getName();
. 跟 new 先运行 . 所以 先运行 Foo.getName = function(){ 输出 2 然后 => new 2
console.log(2);
}
所以还是输出2
new Foo().getName();
new Foo() 跟 . 先执行 new Foo() => 然后执行 this.getName() 本身没有 => 原型 Foo.prototype.getName = function(){
console.log(3);
}
所以输出 3
new new Foo().getName();
new Foo() 跟 . 先执行 new Foo() => 然后执行 this.getName() 本身没有 => 原型 Foo.prototype.getName = function(){
console.log(3);
}
再 new 3
所以还是输出 3
知识点
运算符优先级:

2. 请用 window.prompt 接收用户输入的年份 判断是否是闰年 用三目运算

    var year = window.prompt('请输入判断的年份');
    function isLeapYear(year){
        return (year % 4 ===0 && year % 100!=0)||(year%400===0)?'是闰年':'不是闰年';
    }
    console.log(isLeapYear(year));