提示:从63节开始记录,地址https://www.bilibili.com/video/BV1p4411u7TT?p=63&spm_id_from=pageDriver
文章目录
JS基础
一、使用工厂方法创建对象
大量的重复代码,考虑把重复代码提取出来。——工厂
eg:一个愚蠢的例子
var obj={
name:“孙悟空”,
age:18,
gender:"男",
sayName:function(){
alert(this.name);
}
}
var obj={
name:“猪八戒”,
age:18,
gender:"男",
sayName:function(){
alert(this.name);
}
}
var obj={
name:“沙和尚”,
age:18,
gender:"男",
sayName:function(){
alert(this.name);
}
}
//使用工厂创建对象
function creatPerson(name,age,gender){
var obj=new Object();
obj.name=name;
obj.age=age;
obj.gender=gender;
obj.sayName=function(){
alert(this.name);
}
return obj;
}
var obj2=creatPerson("孙悟空",18,"男");
var obj3=creatPerson("猪八戒",18,"男");
var obj4=creatPerson("沙和尚",18,"男");
obj2.sayName;
obj3.sayName;
obj4.sayName;
二、构造函数
如上例所示(也可以使用上面的函数创建一个小狗的对象,创建后的对象属性都是Object对象,看对象属性分不出是人还是狗),使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型。就导致我们无法区分出多种不同的数据类型
- 创建一个构造函数,专门来创建Person对象的,构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上不同(首字母大写)
- 构造函数和普通函数的区别就是调用方式的不同。
- 普通函数是直接调用、构造函数需要使用new关键字来调用
构造函数的执行流程:
- 立即创建一个新的对象
- 将创建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象
- 执行函数中的代码
- 将创建的对象作为返回值返回
使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类
我们将同一个构造函数创建的对象,称为是该类的实例
加了new就是构造函数,不加就是普通函数。构造函数的首字母大写
function Person(){
}
var per=Person();//普通函数的调用
var per2=new Person();//构造函数的调用
console.log(per);//undefined
console.log(per2);//object object(函数没有返回值,但是per2确实是有个对象,对象哪来的呢)
function Person(name,age,gender){
this.name=name;
this.age=age;
this.gender=gender;
this.sayName=function(){
alert(this.name);
}
}
var per2=new Person("孙悟空",18,"男");//构造函数的调用
var per2=new Person("猪八戒",18,"男");//构造函数的调用
function Dog(){
}
var per3=new Dog();
console.log(per3);//Dog{}
console.log(per2 instanceof Person);//true
console.log(per2 instanceof Object);//true
//所有对象都是Object的后代,所以任何对象和Object在instanceof检查时都会返回true
使用 instanceof 可以检查一个对象是否是一个类的实例
句法:
对象 instanceof 构造函数名字
如果是,返回true,否则false
this的情况
- 当以函数的形式调用时,this就是window
- 当以方法的形式调用时,谁调用方法this就是谁
- 当以构造函数的形式调用时,this就是新创建的那个对象
三、构造函数的修改
//创建一个Person构造函数
function Person(){
this.name=name;
this.age=age;
this.gender=gender;
this.sayName=function(){
alert("Hello,我是"+this.name);
}
}
//创建Person实例
var per=new Person("孙悟空",18,"男");
在Person构造函数中,为每一个对象都添加了一个sayName方法,
目前我们的方法是在构造函数内部创建的,
也就是构造函数每执行一次就会创建一个新的sayName方法,
也就是说所有的sayName都是唯一的。
这样就导致了构造函数每执行一次就会创建一个新的方法,
执行一万次就创建一万个新的方法,而一万个方法都是一模一样的。
这是完全没有必要的,完全可以使所有的对象共享一个方法
提升性能的一种方法:
在构造函数内部中定义的方法,每实例化一次构造函数,就会创建一次方法。
可以把在构造函数内部定义的方法拿出作为全局下的,在构造函数中引用(所有对象共享同一个方法)。如下:
这种方法有一种缺陷:
将函数在全局中定义
- 将函数定义在全局作用域,污染了全局作用域的命名空间
- 而且定义在全局作用域中很不安全(名字不能重复,多人开发中很容易重复了,直接就被覆盖了!)
针对这个缺陷提出了——原型prototype
//创建一个Person构造函数
function Person(){
this.name=name;
this.age=age;
this.gender=gender;
this.sayName=fun;//这儿不需要加括号
}
function fun(){
alert("Hello,我是"+this.name);
}
//创建Person实例
var per=new Person("孙悟空",18,"男");
四、原型对象
我们创建每个函数,解析器都会向函数中添加一个属性:prototype
这个属性对应着一个对象,这个对象就是我们所谓的原型对象
- 如果函数作为普通函数调用prototype没有任何作用
- 当函数以构造函数调用时,它所创建的对象中都会有一个隐函的属性,指向该构造函数的原型对象,我们可以通过_proto_来访问该属性(存的是构造函数的原型对象的地址)
- 原型对象就相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的对象,统一设置到原型对象中。
- 当我们访问对象的一个属性活方法时,它会先在对象的自身中寻找,如果有则直接使用,如果没有则会取原型对象中寻找,如果找到则直接使用
- 以后我们创建构造函数时,可以将这些公共的方法和属性,统一添加到构造函数的原型对象中
function Person1(){
}
console.log(Person1.prototype);//[object Object]
function Person2(){
}
console.log(Person2.prototype==Person1.prototype);//false
说明每个函数都会有自己的prototype属性,都是唯一的,都是自己的
function MyClass(){
}
var mc=new MyClass();
var mc2=new MyClass();
console.log(mc._pro_);
console.log(mc._proto_==MyClass.protostyle);//true
mc.a="我是mc中的a";
console.log(mc.a);//我是mc中的a
console.log(mc2.a);//我是mc中的a
function MyClass(){
}
var mc=new MyClass();
MyClass.prototype.a="123";//在原型对象中添加a
var mc=new MyClass();
console.log(mc.a);//123
//当我们访问对象的一个属性活方法时,它会先在对象的自身中寻找,
//如果有则直接使用,如果没有则会取原型对象中寻找,如果找到则直接使用
//向mc中添加a属性
mc.a="我是mc中的a";
console.log(mc.a);//我是mc中的a
//向MyClass中添加一个方法
MyClass.prototype.sayHello=function(){
console.log("hello");
}
mc.sayHello();//hello
综上,使用原型方法,可以在创建的对象中直接添加方法和属性,不会污染全局作用域。
若在每个对象中都需要,可以放在公共的区域
- 对象.hasOwnProperty()
- 判断对象自身中是否有该属性,使用该方法只有对象自身中含有该属性,才会返回true
- 而hasOwnprototy属性在原型中
console.log(mc._proto_.hasOwnProperty("hasOwnProperty"));//false
//可见在原型中也没有hasOwnProperty,那它是怎么来的?
console.log(mc._proto_._proto_.hasOwnProperty("hasOwnProperty"));//true
五、toString
- 当我们直接在页面中打印一个对象时,实际上输出对象的toString()方法的返回值
- 下面的效果一样
- console.log(per);
- console.log(per.toString());
console.log(per._proto_.hasOwnProperty("toString"));//false
console.log(per._proto_._proto_.hasOwnProperty("toString"));//true
- 这样在原型中加入了,实例化构造函数时,每个对象都会有这个属性了
六、垃圾回收(GC)
七、数组
- 数组中,若读取不存在的索引,不会提示报错,返回undefined
- 向数组的最后一个位置添加元素
- arr[arr.length]=10;
- 数组中可以放任意类型的数据类型(数组,布尔,对象,null,undefined,函数(因为函数也是对象)…)
- 数组中存函数的调用方式:arr0
八、数组的几个方法
在这里插入图片描述
九、数组的遍历
- forEach:只支持IE8以上的浏览器,IE8及以下的浏览器均不支持该方法,所以要兼容IE8,还是使用for循环来遍历
- 需要一个函数作为参数
function fun(){
}
arr.forEach(fun);//参数为一个函数
一般在参数中直接定义函数
十、函数对象的方法
(一)call()
(二)apply()
用apply或者call,可以指定this,参数是谁,this就是谁
(三)arguments 实参
在这里插入图片描述
十一、Date 函数
十二、Math 对象