闭包高级、对象、构造函数、实例化(1) 对象1. 添加// 1.添加属性teacher.address = “北京”// 2. 添加方法teacher.drink = function(){console.log(“I am drinking beer”)}2. 查找// 1. 属性查找teacher.name// 2. 方法查找teacher.teach()3. 删除// 删除属性delete teacher.address// 删除方法delete teacher.teach(2) 创建对象方法1. var obj = new Object();2. var obj = {}3. 自定义构造函数(3) 构造函数1. 大驼峰与普通函数表面上的区别2. 只有 new 了构造函数之后才会有实例 在没有执行之前就不存在this,3. this 指向的是对象4. 通过一个构造函数实例化出来的两个对象之间没有关系,是完全不同的两个对象# 构造函数及实例化原理、包装类(1) 构造函数及实例化原理1. thisthis 没有执行 讨论 this没有意义this 在函数执行的时候指向 window没有实例化的时候指向window当 实例化的时候 this指向 被实例化出来的对象2. 构造函数实例化过程// 1)当构造函数被实例化的时候,相当于函数被执行了,会产生AO,会自动先保存一个this对象(不是空对象)// 2)new 的时候相当于函数跑完了, function Car(color,brand){ // this = { // //因为this指向实例,所以在外界可以通过实例进行访问,访问到this中的的属性 // color:color, // brand:brand // } // 3) 在 this中保存了this相对应的的属性 this.color = color; this.brand = brand; // 构造函数实例化的时候隐式的返回一个引用值,this指向被实例化出来的对象 //return this }### (2) 包装类1. 原始值(string, number, null ,undefined,boolean)没有自己的方法和属性```jsvar a = 123;//原始值a.len = 3;//包装类的步骤//1.new Number(123).len = 3 ;// 将数值通过new Number 转换成数字对象,给这个对象创建一个len属性 赋值为 3//2.delete new Number(123).len;//console.log(a.len);//undefined// 内置的三种构造函数new Number() //转换成数字对象new String() //转换成字符串对象new Boolean()//转换成布尔对象# 原型、原型链、闭包立即执行函数、插件开发(1) 原型 prototype1. 原型 prototype 其实是 function对象的一个属性,打印出来也是对象2. 原型 prototype 是定义 构造函数 构造出来的 每个对象的公共祖先3. 所有被该构造函数构造出来的对象都可以继承原型 prototype 上的属性和方法4. 自己 this 上有的属性和方法是不会往原型上去查找5. 当需要参数进行传值的时候一般写在 this中,写死的属性和方法写在原型 prototype上 // 经验6. 原型中有个默认有个 constructor构造器,指向构造函数本身function Handphone(color, brand, system){this.color = color;this.brand = brand;this.system = system;}Handphone.prototype = {rom: “64G”,ram: ‘6G’,screen: ‘18:9’,call: function(){console.log(‘I am calling somebody’)}}var hp1 = new Handphone()console.log(hp1);// -> 指向一个对象7. constructor 原型上的 constructor 指向构造函数本身 constructor 是可以通过 Handphone.constructor 进行修改的8. protoproto 属于每一个实例化对象每个实例化对象的原型的容器,通过proto访问 prototype9. 当构造函数被实例化new的时候,产生了this 对象,this对象中默认有一个 proto 里面装了原型prototype(2) 插件开发;(function(){语句})()# 原型与原型链深入、对象继承(1) 原型链1. 所有的对象都有原型,包括原型本身2. 沿着proto 往上去找原型上相应的属性,一层一层的往上去继承原型的属性的链条叫做原型链3. 原型链的顶端是Object的原型Professor.prototype.tSkill = ‘JAVA’;function Professor(){}var professor = new Professor();// var professor = {proto:Profressor.prototype}Teacher.prototype = professor;//{proto:Profressor.prototype}function Teacher(){this.mSkill = ‘js/jq’;this.success = {alibaba:’28’,tencent:’30’}}var teacher = new Teacher();// var teacher = {proto:{proto:Profressor.prototype},mkill:’js/jq’}Student.prototype = teacher;function Student(){this.Skill = ‘html’;}var student = new Student();console.log(student.success)4. 原型链上的增删改原始值只能修改改自己,引用值可以修改但不推荐Professor.prototype.tSkill = ‘JAVA’;function Professor(){}var professor = new Professor();// var professor = {proto:Profressor.prototype}Teacher.prototype = professor;//{proto:Profressor.prototype}学function Teacher(){this.mSkill = ‘js/jq’;this.students = 500}var teacher = new Teacher();// var teacher = {proto:{proto:Profressor.prototype},mkill:’js/jq’}Student.prototype = teacher;function Student(){this.Skill = ‘html’;}var student = new Student();student.students += 1;//-> 不会修改原型链上的原始值,会在自己的属性上新建一个值,并附上计算后的属性console.log(student, teacher)(2) 对象继承1. 声明对象var obj1 = {}var obj2 = new Object()// 公司不用这个使用自定义构造函数,原型是构造函数的原型,构造器指向自定义的构造函数Object.create(对象或者null),创建对象,自定义原型的功能2. 不是所有的对象都继承与Object.prototype 如var obj1 = Object.create(null);# 继承深入、call_apply、圣杯模式、模块化(1) 继承function Teacher(){this.name = ‘Mr.Li’;this.tSkill = ‘JAVA’;}Teacher.prototype = {pSkill:’js/jq’,success : {name:1,}}var t = new Teacher;function Student(){this.name = ‘Mr.Wang’}Student.prototpye = Teacher.prototype;// 公共原型// 这样的继承使得两个原型的指向是同一个地址,一个修改原始值另一也会修改var s = new Student();(2) 解决继承(圣杯模式)1. 定义一个缓冲构造函数2. 将要Teacher.prototype赋值给缓冲的原型3. 实例化缓冲实例对象4. 将实例化的缓冲对象赋值给Student.prototypevar inherit = (function test(){var Buffer = function(){};return function(Target, Origin){Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}})()Teacher.prototype.name = “Mr.Zhang”function Teacher(){}function Student(){}inherit(Student, Teacher);var t = new Teacher();var s = new Student();console.log(t, s)(2) call_apply1. 改变this的指向function Car(brand, color){this.brand = brand;this.color = color;}var newcar = {};// Car.call(newcar,’Banz’,’red’)Car.apply(newcar,[‘Banz’,’red’])console.log(newcar)# 对象属性遍历、this、caller_callee(1) 对象枚举 -> 遍历var arr = [1, 2, 3, 4, 5, 6]// 循环一个数组 就是遍历一个数组for (var i = 0; i < arr.length; i++){console.log(arr[i]);}var car = {brand: ‘Benz’,color: ‘red’,displacement: ‘3.0’,lang: ‘3’,width: ‘5’}// for…in 既可以遍历对象也可以遍历数组for (var key in car){console.log(key)console.log(key + ‘:’ + car[key])// javascript 内置的系统 先将 car.key -> car[‘key’]}var arr = [1, 2, 3, 4, 5, 6];for (var i in arr){console.log(arr[i])}(2) 对象.hasOwnProperty(属性名) 排除原型上自定义的属性function Car(){this.brand = ‘Benz’,this.color = ‘red’,this.displacement = ‘3.0’}Car.prototype = {lang:5,width:2.5,}Object.prototype.name = ‘Object’var car = new Car();console.log(car);for (var key in car){// console.log(key + ‘:’ + car[key])// for in 在原型链上所有自己定义原型的属性会全部被打印出来if(car.hasOwnProperty(key)){ // 使用car.hasOwnProperty 去掉原型链上自定义的属性console.log(key + ‘:’ + car[key])}}(3) 三种判断数组的方法1. console.log(a.constructor);2. console.log(a instanceof Array);3. console.log(Object.prototype.toString.call(a));(4) this 的指向1. 全局的 this 指向 window2. 预编译的时候 this 指向 window3. 构造函数实例化的时候 this 指向被实例化出来的对象4. call/apply 更改 this 的指向(5) callee/callerfunction test(a, b, c){console.log(arguments.callee.length)}test(1, 2, 3)// arguments.callee 执行到这一句的时候,返回正在被执行的函数对象// caller 返回的是当前被调用函数的函数引用#三目运算、对象克隆、浅拷贝、深拷贝(1) 三目运算格式条件 ? 满足条件后执行的语句 // 直接自带 return: 不满足条件后执行的语句(2) 浅拷贝浅拷贝就是将对象中的所有元素复制到新的对象中浅拷贝对于原始值类型与引用类型的方式有区别原始值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象在副本中对子元素引用类型的字段值被修改后,源对象的值也将被修改。var person2 = {};console.log(person2)for (var key in person1){person2[key] = person1[key];}person2.name = ‘李四’;console.log(person1, person2)(3) 深拷贝深拷贝也同样是将对象中的所有字段复制到副本对象中对于子元素的引用类型也是创建并复制在副本中对子元素引用类型的字段值被修改后,源对象的值不会被修改。function deep(origin, target){var toStr = Object.prototype.toString,arrType = ‘[object Array]’,target = target || {}; // 防止用户没有传 targetfor(var key in origin){ // 循环需要被拷贝的对象if(origin.hasOwnProperty(key)){ // 判断属性是不是被拷贝对象自身的属性, 剔除prototype上的属性if(typeof(origin[key]) === ‘object’ && origin[key] !== null){ // 判断被拷贝对象的值是不是一个引用值,需要排除nullif(toStr.call(origin[key]) === arrType){ // 判断被拷贝对象的值是不是一个数组target[key] = [] // 如果是数组 将目标对象的值设为空数组}else{target[key] = {}// 如果是对象 将目标对象的值设为空对象}deep(origin[key], target[key]);// 递归调用本身}else{ // 被拷贝对象的值是原始值得时候直接进行拷贝 ,递归的出口target[key] = origin[key];}}}return target; // 返回目标对象}闭包高级、对象、构造函数、实例化(1) 对象1. 添加// 1.添加属性teacher.address = “北京”// 2. 添加方法teacher.drink = function(){console.log(“I am drinking beer”)}2. 查找// 1. 属性查找teacher.name// 2. 方法查找teacher.teach()3. 删除// 删除属性delete teacher.address// 删除方法delete teacher.teach(2) 创建对象方法1. var obj = new Object();2. var obj = {}3. 自定义构造函数(3) 构造函数1. 大驼峰与普通函数表面上的区别2. 只有 new 了构造函数之后才会有实例 在没有执行之前就不存在this,3. this 指向的是对象4. 通过一个构造函数实例化出来的两个对象之间没有关系,是完全不同的两个对象# 构造函数及实例化原理、包装类(1) 构造函数及实例化原理1. thisthis 没有执行 讨论 this没有意义this 在函数执行的时候指向 window没有实例化的时候指向window当 实例化的时候 this指向 被实例化出来的对象2. 构造函数实例化过程// 1)当构造函数被实例化的时候,相当于函数被执行了,会产生AO,会自动先保存一个this对象(不是空对象)// 2)new 的时候相当于函数跑完了, function Car(color,brand){ // this = { // //因为this指向实例,所以在外界可以通过实例进行访问,访问到this中的的属性 // color:color, // brand:brand // } // 3) 在 this中保存了this相对应的的属性 this.color = color; this.brand = brand; // 构造函数实例化的时候隐式的返回一个引用值,this指向被实例化出来的对象 //return this }### (2) 包装类1. 原始值(string, number, null ,undefined,boolean)没有自己的方法和属性```jsvar a = 123;//原始值a.len = 3;//包装类的步骤//1.new Number(123).len = 3 ;// 将数值通过new Number 转换成数字对象,给这个对象创建一个len属性 赋值为 3//2.delete new Number(123).len;//console.log(a.len);//undefined// 内置的三种构造函数new Number() //转换成数字对象new String() //转换成字符串对象new Boolean()//转换成布尔对象# 原型、原型链、闭包立即执行函数、插件开发(1) 原型 prototype1. 原型 prototype 其实是 function对象的一个属性,打印出来也是对象2. 原型 prototype 是定义 构造函数 构造出来的 每个对象的公共祖先3. 所有被该构造函数构造出来的对象都可以继承原型 prototype 上的属性和方法4. 自己 this 上有的属性和方法是不会往原型上去查找5. 当需要参数进行传值的时候一般写在 this中,写死的属性和方法写在原型 prototype上 // 经验6. 原型中有个默认有个 constructor构造器,指向构造函数本身function Handphone(color, brand, system){this.color = color;this.brand = brand;this.system = system;}Handphone.prototype = {rom: “64G”,ram: ‘6G’,screen: ‘18:9’,call: function(){console.log(‘I am calling somebody’)}}var hp1 = new Handphone()console.log(hp1);// -> 指向一个对象7. constructor 原型上的 constructor 指向构造函数本身 constructor 是可以通过 Handphone.constructor 进行修改的8. protoproto 属于每一个实例化对象每个实例化对象的原型的容器,通过proto访问 prototype9. 当构造函数被实例化new的时候,产生了this 对象,this对象中默认有一个 proto 里面装了原型prototype(2) 插件开发;(function(){语句})()# 原型与原型链深入、对象继承(1) 原型链1. 所有的对象都有原型,包括原型本身2. 沿着proto 往上去找原型上相应的属性,一层一层的往上去继承原型的属性的链条叫做原型链3. 原型链的顶端是Object的原型Professor.prototype.tSkill = ‘JAVA’;function Professor(){}var professor = new Professor();// var professor = {proto:Profressor.prototype}Teacher.prototype = professor;//{proto:Profressor.prototype}function Teacher(){this.mSkill = ‘js/jq’;this.success = {alibaba:’28’,tencent:’30’}}var teacher = new Teacher();// var teacher = {proto:{proto:Profressor.prototype},mkill:’js/jq’}Student.prototype = teacher;function Student(){this.Skill = ‘html’;}var student = new Student();console.log(student.success)4. 原型链上的增删改原始值只能修改改自己,引用值可以修改但不推荐Professor.prototype.tSkill = ‘JAVA’;function Professor(){}var professor = new Professor();// var professor = {proto:Profressor.prototype}Teacher.prototype = professor;//{proto:Profressor.prototype}学function Teacher(){this.mSkill = ‘js/jq’;this.students = 500}var teacher = new Teacher();// var teacher = {proto:{proto:Profressor.prototype},mkill:’js/jq’}Student.prototype = teacher;function Student(){this.Skill = ‘html’;}var student = new Student();student.students += 1;//-> 不会修改原型链上的原始值,会在自己的属性上新建一个值,并附上计算后的属性console.log(student, teacher)(2) 对象继承1. 声明对象var obj1 = {}var obj2 = new Object()// 公司不用这个使用自定义构造函数,原型是构造函数的原型,构造器指向自定义的构造函数Object.create(对象或者null),创建对象,自定义原型的功能2. 不是所有的对象都继承与Object.prototype 如var obj1 = Object.create(null);# 继承深入、call_apply、圣杯模式、模块化(1) 继承function Teacher(){this.name = ‘Mr.Li’;this.tSkill = ‘JAVA’;}Teacher.prototype = {pSkill:’js/jq’,success : {name:1,}}var t = new Teacher;function Student(){this.name = ‘Mr.Wang’}Student.prototpye = Teacher.prototype;// 公共原型// 这样的继承使得两个原型的指向是同一个地址,一个修改原始值另一也会修改var s = new Student();(2) 解决继承(圣杯模式)1. 定义一个缓冲构造函数2. 将要Teacher.prototype赋值给缓冲的原型3. 实例化缓冲实例对象4. 将实例化的缓冲对象赋值给Student.prototypevar inherit = (function test(){var Buffer = function(){};return function(Target, Origin){Buffer.prototype = Origin.prototype;Target.prototype = new Buffer();Target.prototype.constructor = Target;Target.prototype.super_class = Origin;}})()Teacher.prototype.name = “Mr.Zhang”function Teacher(){}function Student(){}inherit(Student, Teacher);var t = new Teacher();var s = new Student();console.log(t, s)(2) call_apply1. 改变this的指向function Car(brand, color){this.brand = brand;this.color = color;}var newcar = {};// Car.call(newcar,’Banz’,’red’)Car.apply(newcar,[‘Banz’,’red’])console.log(newcar)# 对象属性遍历、this、caller_callee(1) 对象枚举 -> 遍历var arr = [1, 2, 3, 4, 5, 6]// 循环一个数组 就是遍历一个数组for (var i = 0; i < arr.length; i++){console.log(arr[i]);}var car = {brand: ‘Benz’,color: ‘red’,displacement: ‘3.0’,lang: ‘3’,width: ‘5’}// for…in 既可以遍历对象也可以遍历数组for (var key in car){console.log(key)console.log(key + ‘:’ + car[key])// javascript 内置的系统 先将 car.key -> car[‘key’]}var arr = [1, 2, 3, 4, 5, 6];for (var i in arr){console.log(arr[i])}(2) 对象.hasOwnProperty(属性名) 排除原型上自定义的属性function Car(){this.brand = ‘Benz’,this.color = ‘red’,this.displacement = ‘3.0’}Car.prototype = {lang:5,width:2.5,}Object.prototype.name = ‘Object’var car = new Car();console.log(car);for (var key in car){// console.log(key + ‘:’ + car[key])// for in 在原型链上所有自己定义原型的属性会全部被打印出来if(car.hasOwnProperty(key)){ // 使用car.hasOwnProperty 去掉原型链上自定义的属性console.log(key + ‘:’ + car[key])}}(3) 三种判断数组的方法1. console.log(a.constructor);2. console.log(a instanceof Array);3. console.log(Object.prototype.toString.call(a));(4) this 的指向1. 全局的 this 指向 window2. 预编译的时候 this 指向 window3. 构造函数实例化的时候 this 指向被实例化出来的对象4. call/apply 更改 this 的指向(5) callee/callerfunction test(a, b, c){console.log(arguments.callee.length)}test(1, 2, 3)// arguments.callee 执行到这一句的时候,返回正在被执行的函数对象// caller 返回的是当前被调用函数的函数引用#三目运算、对象克隆、浅拷贝、深拷贝(1) 三目运算格式条件 ? 满足条件后执行的语句 // 直接自带 return: 不满足条件后执行的语句(2) 浅拷贝浅拷贝就是将对象中的所有元素复制到新的对象中浅拷贝对于原始值类型与引用类型的方式有区别原始值类型字段的值被复制到副本中后,在副本中的修改不会影响源对象对应的值引用类型的字段被复制到副本中的却是引用类型的引用,而不是引用的对象在副本中对子元素引用类型的字段值被修改后,源对象的值也将被修改。var person2 = {};console.log(person2)for (var key in person1){person2[key] = person1[key];}person2.name = ‘李四’;console.log(person1, person2)(3) 深拷贝深拷贝也同样是将对象中的所有字段复制到副本对象中对于子元素的引用类型也是创建并复制在副本中对子元素引用类型的字段值被修改后,源对象的值不会被修改。function deep(origin, target){var toStr = Object.prototype.toString,arrType = ‘[object Array]’,target = target || {}; // 防止用户没有传 targetfor(var key in origin){ // 循环需要被拷贝的对象if(origin.hasOwnProperty(key)){ // 判断属性是不是被拷贝对象自身的属性, 剔除prototype上的属性if(typeof(origin[key]) === ‘object’ && origin[key] !== null){ // 判断被拷贝对象的值是不是一个引用值,需要排除nullif(toStr.call(origin[key]) === arrType){ // 判断被拷贝对象的值是不是一个数组target[key] = [] // 如果是数组 将目标对象的值设为空数组}else{target[key] = {}// 如果是对象 将目标对象的值设为空对象}deep(origin[key], target[key]);// 递归调用本身}else{ // 被拷贝对象的值是原始值得时候直接进行拷贝 ,递归的出口target[key] = origin[key];}}}return target; // 返回目标对象}