一、插件化
1.1、需要立即执行的插件「比如轮播图」
// 插件化// 需要立即执行的插件,比如轮播图;(functin(){var Slider = function(){};Slider.prototype = {}window.Slider = Slider;})();
1.2、不需要立即执行的插件
不需要立即执行的插件,我们在全局声明一个变量将其保存起来,需要执行的时候再随时调用即可
// 插件化// 不需要立即执行的插件,只需要在全局声明一个变量将其保存起来;后期什么时候需要执行再调用即可var inherit = (function(){var Buffer = function(){};return function(origin, target){Buffer.prototype = origin.prototype;target.prototype = new Buffer();target.prototype.constructor = origin;target.prototype.supper_class = origin;}})();
二、三目运算符「三元运算符」
基本语法: 条件判断 ? 条件成立要做的事情 :条件不成立要做的事情;
var a = 5;if(a > 0){console.log('大于0');}else{console.log('小于0');}// 改为三目运算符var a = 5;a > 0 ? console.log('大于0'): console.log('小于0');
三元运算符有return的作用
// 三元运算符有return的作用var a = 5,str;if(a > 0){str = '大于0';}else{str = '小于0'}// 改为三目运算符var a = 5;var str = a > 0 ? str = '大于0': str = '小于0';console.log(str);
三元运算符练习
// 三元运算符的练习var a = 5,str;if(a > 0){if(a > 3){str = '大于3';}else{str = '小于等于3';}}else{str = '小于等于0'}console.log(str);// 改为三目运算符var a = 5;var str = a > 0 ? (a > 3 ? str = '大于3': str = '小于等于3'): str = '小于等于0';console.log(str);
三、关于字符串比较的面试题
字符串和字符换比较,是逐位比较字符串对应的ASCII码所对应的十进制值的大小
// 一道关于字符串的面试题// 字符串和字符换比较,是逐位比较字符串对应的ASCII码所对应的十进制值的大小var str = 89 > 9 ? ('89' > '9' ? '内层通过了': '内层未通过'): '外层通过了' ;console.log(str);
四、对象的浅克隆
4.1、浅克隆之对象赋值
- 对象浅克隆之对象赋值,这种方式严格来说不叫克隆
使用对象赋值的方法,两个对象共用的是同一个堆内存地址
// 对象的浅克隆和深克隆 clone// 对象的浅克隆// 对象的赋值,不叫克隆var person1 = {name: '良雨',age: 10,sex: 'male',}// 对象的赋值,共用同一个堆内存地址var person2 = person1;console.log(person2);console.log(person1 == person2);person2.age = 20;console.log(person1, person2);
4.2、浅克隆之循环「for in」
先创建一个空对象,然后把原始对象进行循环,把属性赋值给新对象
- 注意:for in 循环会把原型及其原型链上的自定义属性或者是方法循环到 「 hasOwnProperty」
浅拷贝只能处理第一层,而且并没有深层次的处理对象中的引用值
// 浅克隆 for in循环的方式// 创建一个空对象,用for in循环原始对象,然后将属性名和值存入到新的对象之中// 注意:for in循环是会把原型及其原型链上的自定义的属性和方法都循环出来的var obj1 = {name: 'kola',age: 10,sex: 'male'}var obj2 = {};for(var key in obj1){obj2[key] = obj1[key];}console.log(obj2);obj2.name = 'Lucy';console.log(obj1, obj2);
浅拷贝只能处理第一层,而且不能深层次处理引用值;在用for in循环的时候,会把原型及其原型链上的自定义属性和方法循环到
// 浅克隆 for in循环的方式// 创建一个空对象,用for in循环原始对象,然后将属性名和值存入到新的对象之中// 注意:for in循环是会把原型及其原型链上的自定义的属性和方法都循环出来的var obj1 = {name: 'kola',age: 10,sex: 'male'}// 可能会多次用到,进行封装var obj2 = {};// for(var key in obj1){// obj2[key] = obj1[key];// }// 执行封装的clone方法clone(obj1, obj2);console.log(obj2);obj2.name = 'Lucy';console.log(obj1, obj2);// 对象浅拷贝 第一版封装// 没有考虑用户不新建空对象的情况,也没有考虑到for in的缺陷function clone(origin, target){for(var key in origin){target[key] = origin[key]}}// 浅克隆第二版封装function clone(origin, target){var target = target || {};for(var key in origin){// 提出原型及其原型链上的自定义属性和方法if(origin.hasOwnProperty(key)){target[key] = origin[key];}}return target;}
4.3、浅克隆封装
function clone(origin, target){var target = target || {};for(var key in origin){if(origin.hasOwnProperty(key)){target[key] = origin[key];}}return target;}
4.4、浅克隆存在的问题
不能深层次处理引用值
只能处理第一层,出现对象嵌套的情况就无法处理了 ```javascript
// 浅拷贝的问题:// + 不能深层次处理引用值// + 只能处理第一层,出现对象嵌套的情况就无法处理了Object.prototype.num = '11';var person1 = {name: 'kola',age: 18,sex: 'male',son: {first: 'Jenny',second: 'Lucy',third: 'Tone'}}// 浅克隆封装function clone(origin, target){var target = target || {};for(var key in origin){if(origin.hasOwnProperty(key)){target[key] = origin[key];}}return target;}
// 调用封装好的浅克隆方法var person2 = clone(person1);console.log(person1, person2);// 浅克隆无法处理深层次的引用值person2.name = '李四';person2.son = {forth: '李小明',five: '李华'};console.log(person1, person2);
<a name="Q5i7f"></a># 五、对象的深克隆<a name="BFv2R"></a>## 5.1、对象深克隆思路分析及其封装- 先处理用户体验 target = target || {}- 用for in遍历原始对象的属性- 在遍历原始对象属性的时候,要注意排除原型及其原型链上的自定义属性和方法「for in」会遍历到原型及其原型链上的自定义的属性和方法,可以用「hasOwnProperty」来解决- 排除完原型和原型链上的自定义方法以后,先判断对象的属性是否是引用数据类型「注意排除null」- 判断是对象之后,再看是不是数组,如果是数组就创建一个空数组,如果是对象就创建一个空对象- 使用递归,调用自己封装的这个深克隆的方法,来循环深层次的对象- 如果不是引用数据类型值,那就 target[key] = origin[key]- 最后将target返回出去```javascript// 对象的深克隆// + 先处理用户体验 var target = target || {}// + 用for in循环原始对象,注意for in在循环的时候会把原型及其原型链上的自定义属性或者是方法循环出来,可以用hasOwnProperty来解决// + 循环完以后先判断其是否为对象,注意排除null// + 判断是否为对象以后,再判断是否是数组,如果是数组就创建一个空数组,如果是对象就创建一个空对象// + 递归循环深层次的对象 deepClone(origin[key], target[key])// + 如果不是对象就 target[key] = origin[key]// + 最后 return target// 深克隆方法封装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){if(toStr.call(origin[key]) === arrType){target[key] = [];}else{target[key] = {};}deepClone(origin[key], target[key]);}else{target[key] = origin[key];}}}return target;}Object.prototype.num = '11';var person1 = {name: '张三',age: 18,sex: 'male',height: 180,children: {first: {name: '张一',age: 22},second: {name: '张二',age: 20},third: {name: '张三',age: 10},},car: ['Benz', 'Mazda']};var person2 = deepClone(person1);person2.name = '李四';person2.children.forth = {name: '李五',age: 8}person2.car.push('BYD');console.log(person1, person2);
5.2、对象深克隆封装的优化 「三目运算符版本」
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){toStr.call(origin[key]) === arrType ? target[key] = []: target[key] = {};deepClone(origin[key], target[key]);}}else{target[key] = origin[key];}}return target;}
5.3、利用JSON的方法
JSON方法是不能克隆对象上的方法的
// 利用JSON的方法实现对象的克隆// JSON这个方法,是不能克隆对象上的方法的var str = JSON.stringify(person1);var person2 = JSON.perse(str);
六、面试题
// 面试题function test(){console.log(foo);var foo = 2;console.log(foo);console.log(a);}test();console.log(a);console.log(typeof(a));
函数预编译
寻找形参和变量声明
- 统一形参和实参的值
- 寻找函数声明并赋值
执行
// 面试题// 预编译阶段// + 寻找形参和变量声明// + 统一形参和实参的值// + 寻找函数声明并赋值// + 执行function a(){var test;test();function test(){console.log(1);}}a();
this指向的面试题「做错两遍了重点注意」
// 面试题var name = '222';var a = {name: '111',say: function(){console.log(this.name);}}var func = a.say;// say: function(){// console.log(this.name);// }func(); // '222'a.say(); // '111'var b = {name: '333',say: function(){func();}}b.say(a.say); // '333' 错的b.say = a.say;b.say(); // '333'
this指向和call/apply面试题
// this指向和call/apply面试题function test(){var marty = {name: 'marty',printName: function(){console.log(this.name);}}var test1 = {name: 'test1'};var test2 = {name: 'test2'};var test3 = {name: 'test'};test3.printName = marty.printName;marty.printName.call(test1);marty.printName.call(test2);marty.printName();test3.printName();}test();
面试题「做错了留意一下」
// 面试题var bar = {a: '1'};function test(){bar.a = 'a';Object.prototype.b = 'b';return function inner(){console.log(bar.a);console.log(bar.b);}}test()();
七、一道超难的面试题
做错了无数遍,需要留意 ```javascript
// 作业:说出为什么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(); // 2getName(); // 4Foo().getName(); // 1getName(); // 1new Foo.getName(); // 2new Foo().getName(); // 3new new Foo().getName(); // 3// 1. 寻找变量声明// 2. 寻找函数声明并赋值// 3. 执行赋值// 优先级问题: () > . > newGO = {Foo: function(){...}getName: // undefined// function (){console.log(1)}}
[JS运算符优先级](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#%E6%B1%87%E6%80%BB%E8%A1%A8)<a name="vlkUQ"></a># 八、作业从window.prompt输入一个年份,判断其是否是闰年「请用三目运算符」```javascript// 第十四课时作业:从wp输入一个年份,判断是否是闰年var year = window.prompt('请输入年份');function isLeapYear(year){var year = Number(year);if((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0){return '闰年';}else{return '不是闰年';}}console.log(isLeapYear(year));// 三目运算符版var year = window.prompt('请输入年份');function isLeapYear(year){var year = Number(year);return year = ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) ? '闰年': '不是闰年';}console.log(isLeapYear(year));
