JavaScript--高级---1
1.工厂模式和自定义构造函数的区别
工厂模式:
* 函数名是小写
* 有new,
* 有返回值
* new之后的对象是当前的对象
* 直接调用函数就可以创建对象
* 自定义构造函数:
* 函数名是大写(首字母)
* 没有new
* 没有返回值
* this是当前的对象
* 通过new的方式来创建对象
2.实例对象和构造函数之间的关系:
1. 实例对象是通过构造函数来创建的---创建的过程叫实例化
2.如何判断对象是不是这个数据类型?
1) 通过构造器的方式 实例对象.构造器==构造函数名字
2) 对象 instanceof 构造函数名字
3.原型
实例对象中有__proto__这个属性,叫原型,也是一个对象,这个属性是给浏览器使用,不是标准的属性----->__proto__----->可以叫原型对象
构造函数中有prototype这个属性,叫原型,也是一个对象,这个属性是给程序员使用,是标准的属性------>prototype--->可以叫原型对象
* 实例对象的__proto__和构造函数中的prototype相等----->true
* 又因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
* 实例对象的__proto__指向了构造函数的原型对象prototype
4.通过原型来添加方法,解决数据共享,节省内存空间
function Person(name,age) { this.name=name; this.age=age; } //通过原型来添加方法,解决数据共享,节省内存空间 Person.prototype.eat=function () { console.log("吃凉菜"); }; var p1=new Person("小明",20); var p2=new Person("小红",30); console.log(p1.eat==p2.eat);//true console.dir(p1); console.dir(p2);
5.构造函数、实例对象和原型对象的关系
构造函数可以实例化对象。
构造函数中有一个属性叫prototype,是构造函数的原型对象。
构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数。
实例对象的原型对象(__proto__)指向的是该构造函数的原型对象。
构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的。
6.继承
1)js中通过原型来实现继承(相同的代码太多,造成了代码的冗余(重复的代码))
function Person(name,age,sex) { this.name=name; this.sex=sex; this.age=age; } Person.prototype.eat=function () { console.log("人可以吃东西"); }; Person.prototype.sleep=function () { console.log("人在睡觉"); }; Person.prototype.play=function () { console.log("生活就是不一样的玩法而已"); }; function Student(score) { this.score=score; } //改变学生的原型的指向即可==========>学生和人已经发生关系 Student.prototype=new Person("小明",10,"男"); Student.prototype.study=function () { console.log("学习很累很累的哦."); }; //相同的代码太多,造成了代码的冗余(重复的代码) var stu=new Student(100); console.log(stu.name); console.log(stu.age); console.log(stu.sex); stu.eat(); stu.play(); stu.sleep(); console.log("下面的是学生对象中自己有的"); console.log(stu.score); stu.study();
2)借用构造函数(父级类别中的方法不能继承,解决了属性问题)
function Person(name, age, sex, weight) { this.name = name; this.age = age; this.sex = sex; this.weight = weight; } Person.prototype.sayHi = function () { console.log("您好"); }; function Student(name,age,sex,weight,score) { //借用构造函数 Person.call(this,name,age,sex,weight); this.score = score; } var stu1 = new Student("小明",10,"男","10kg","100"); console.log(stu1.name, stu1.age, stu1.sex, stu1.weight, stu1.score); var stu2 = new Student("小红",20,"女","20kg","120"); console.log(stu2.name, stu2.age, stu2.sex, stu2.weight, stu2.score); var stu3 = new Student("小丽",30,"妖","30kg","130"); console.log(stu3.name, stu3.age, stu3.sex, stu3.weight, stu3.score);
3)组合继承:原型继承+借用构造函数继承(既能解决属性问题,又能解决方法问题)
function Person(name,age,sex) { this.name=name; this.age=age; this.sex=sex; } Person.prototype.sayHi=function () { console.log("阿涅哈斯诶呦"); }; function Student(name,age,sex,score) { //借用构造函数:属性值重复的问题 Person.call(this,name,age,sex); this.score=score; } //改变原型指向----继承 Student.prototype=new Person();//不传值 Student.prototype.eat=function () { console.log("吃东西"); }; var stu=new Student("小黑",20,"男","100分"); console.log(stu.name,stu.age,stu.sex,stu.score); stu.sayHi(); stu.eat(); var stu2=new Student("小黑黑",200,"男人","1010分"); console.log(stu2.name,stu2.age,stu2.sex,stu2.score); stu2.sayHi(); stu2.eat();
4)拷贝继承(就是把对象中需要共享的属性或者犯法,直接遍历的方式复制到另一个对象中)
function Person() { } Person.prototype.age=10; Person.prototype.sex="男"; Person.prototype.height=100; Person.prototype.play=function () { console.log("玩的好开心"); }; var obj2={}; //Person的构造中有原型prototype,prototype就是一个对象,那么里面,age,sex,height,play都是该对象中的属性或者方法 for(var key in Person.prototype){ obj2[key]=Person.prototype[key]; } console.dir(obj2); obj2.play();
7.函数中的this的指向
普通函数中的this是谁?-----window
对象.方法中的this是谁?----当前的实例对象
定时器方法中的this是谁?----window
构造函数中的this是谁?-----实例对象
原型对象方法中的this是谁?---实例对象
8.闭包
闭包:函数A中有一个函数B,函数B中可以访问函数A中的变量或者数据,此时形成闭包。
闭包的模式:函数模式(里面的返回作为返回值),对象模式(里面的对象作为返回值)。
闭包的作用:缓存数据---是优点也是缺点。
闭包的作用缓存数据:只要是想把数据保存起来,就把这个数据放在闭包中(就是在外层函数和里层函数的中间)
正因为闭包的出现缓存了数据,那么函数中的变量就没有得到及时的释放,,延长作用域了。
//函数模式的闭包 function f1() { var num = 10; return function () { console.log(num); } } var ff=f1(); ff(); //对象模式的闭包 function f3() { return { age:100, getAge:function () { console.log(this.age); } } }
产生相同的随机数,函数调用多次
function showRandom2() { var random= parseInt(Math.random()*10+1);//产生一次随机数 return function () { console.log(random);//每次输出的都是最开始产生的随机数字的值 } } var ff=showRandom2();//调用一次 ff(); ff(); ff();
9.沙箱
沙箱:环境,黑盒,---在虚拟的世界中,模拟真实世界的场景,做实验,实验的结果和真实世界的结果一样,但是不会影响真实的世界。
//沙箱 (function (x) { //局部变量 var num=1000; console.log(num);//1000 }(100)); //全局变量 var num=10000; console.log(num);//10000
//沙箱可以解决命名冲突的问题 (function () { var x=10; function f1() { } }()); (function () { var x=10; function f1() { } }());
10.call()、apply()、bind()的区别
11.浅拷贝
浅拷贝:拷贝就是复制,就相当于把一个对象中的所有的内容,复制一份给另一个对象,直接复制,或者说,就是把一个对象的地址给了另一个对象,他们指向相同,两个对象之间有共同的属性或者方法,都可以使用。
var obj1={ age:10, sex:"男", car:["奔驰","宝马","特斯拉","奥拓"] }; //另一个对象 var obj2={}; //写一个函数,作用:把一个对象的属性复制到另一个对象中,浅拷贝 //把a对象中的所有的属性复制到对象b中 function extend(a,b) { for(var key in a){ b[key]=a[key]; } } extend(obj1,obj2); console.dir(obj2);//开始的时候这个对象是空对象 console.dir(obj1);//有属性
12. 深拷贝
深拷贝:拷贝还是复制,深:把一个对象中所有的属性或者方法,一个一个的找到.并且在另一个对象中开辟相应的空间,一个一个的存储到另一个对象中。
var obj1={ age:10, sex:"男", car:["奔驰","宝马","特斯拉","奥拓"], dog:{ name:"大黄", age:5, color:"黑白色" } }; var obj2={};//空对象 //通过函数实现,把对象a中的所有的数据深拷贝到对象b中 function extend(a,b) { for(var key in a){ //先获取a对象中每个属性的值 var item=a[key]; //判断这个属性的值是不是数组 if(item instanceof Array){ //如果是数组,那么在b对象中添加一个新的属性,并且这个属性值也是数组 b[key]=[]; //调用这个方法,把a对象中这个数组的属性值一个一个的复制到b对象的这个数组属性中 extend(item,b[key]); }else if(item instanceof Object){//判断这个值是不是对象类型的 //如果是对象类型的,那么在b对象中添加一个属性,是一个空对象 b[key]={}; //再次调用这个函数,把a对象中的属性对象的值一个一个的复制到b对象的这个属性对象中 extend(item,b[key]); }else{ //如果值是普通的数据,直接复制到b对象的这个属性中 b[key]=item; } } } extend(obj1,obj2); console.dir(obj1); console.dir(obj2);
13.正则表达式
正则表达式:也叫规则表达式,按照一定的规则组成的一个表达式,这个表达式的作用主要是匹配字符串的。
正则表达式的作用:匹配字符串的。
正则表达式的组成:是由元字符或者是限定符组成的一个式子。
规则:
. 除了\n以外的任意一个单个字符
[] 范围
() 分组,提升优先级
| 或者
* 0-多次
+ 1-多次
? 0-1次
{0,} 和*一样
{1,} 和+
{0,1} 和?
\d 数字中的一个
\D 非数字
\s 空白符
\S 非空白符
\W 特殊符号
\w 非特殊符号 _
^ 取反,以什么开始
$ 以什么结束
\b 单词边界
14.伪数组和数组的区别
真数组的长度是可变的
伪数组的长度不可变
真数组可以使用数组中的方法
伪数组不可以使用数组中的方法