什么是面向对象?
对象是类的实例,类是对象的抽象
对象的本质:属性和方法的集合
学过的对象
Array、String、Math、Date …….
创建对象的方式:
1、字面量 var obj = {}
2、通过new运算符 var obj = new Object()
3.构造函数
用来构造(创建)对象的函数
他在声明的时候跟普通函数没有区别
用new运算符加上函数的调用,调用的结果就是一个对象
构造函数中的this指的是即将要new的那个对象
构造函数就是封装一个函数,可以用来通过new的方式得到一系列特征相同的对象
function Student(name){
//再构造函数里,this值即将要new的那个对象
//给this这个对象新增自定义属性和方法
this.name = name;
this.speak = function(){
alert(this.name);
}
}
let stu = new Student("xiaohong");//实例化对象
//关于使用new实例化对象时:发生了以下四件事情
//1.开辟申请一块空间来存储对象
//2.把this设置为当前对象
//3.设置属和方法的值
//4.将this对象返回
console.log(stu);
stu.speak();
let stu1 = new Student("xiaohei");
console.log(stu1);
stu1.speak();
4、ES6语法糖(class…)
class Student {
//构造
constructor (name) {
this.name = name;
}
//speak默认就在原型上
speak () {
alert(this.name);
}
}
let stu = new Student("xiaogang");
console.log(stu);//Student name: "xiaogang" __proto__: Object
stu.speak();
原型
原型是函数的伴生体
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法
prototype(原型)属性指向的对象就是原型对象
js中万物皆对象,因此原型也是对象,可以通过原型实现对象属性的继承
实例化一个对象后该对象就有一个proto属性,且指向实例化对象的构造函数的prototype属性
创建一个函数后该函数就有一个prototype属性,且指向该函数的原型对象的proto属性
function fn(a,b){}
console.dir(fn);
function Student(name){
this.name = name;
this.speak = function(){
alert(this.name);
}
}
//Student的原型对象
Student.prototype.say = function(){
alert("I am" + this.name);
}
Student.prototype.age = 18;
let stu = new Student("xiaohong");
let stu1 = new Student("xiaohei");
console.log(stu.speak === stu1.speak);
//stu.say();
//stu1.say();
console.log(stu.say === stu1.say);
console.dir(Student);
console.log(stu, stu1);
//原型链
console.log(stu.__proto__ === Student.prototype);
console.log(Student.prototype.__proto__ === Object.prototype);
let str = stu.toString();
console.log(str);
对于上面js代码里的原型链解释如链接图所示:
https://upload-images.jianshu.io/upload_images/15859737-d8659a4ce2872ad0.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp
也证明了函数作为特殊的对象,是函数也是对象,即万物皆是对象。
几个必记的属性和方法
constructor prototype里面的constructor指向当前对象的构造函数
proto === [[prototype]] 指向父类的prototype
prototype 指向当前对象的原型对象
instanceof 运算符,判断当前对象是否是另一个对象的实例
function Fn(){}
//var Fn = new Function();
//console.dir(Fn);
//console.log(Fn.__proto__ === Function.prototype)
console.log(Fn instanceof Function); //true
console.log(Fn instanceof Object); //true
var fn = new Fn();
console.log(fn instanceof Fn);
console.log(fn instanceof Function); //false 原型链没有指向Function
console.log(fn instanceof Object);
hasOwnProperty 判断对象上是否存在某个属性,并且这个方法会过滤到原型上的属性
function Student (name){
this.name = name;
}
Student.prototype.say = function(){
alert(this.name);
}
var stu = new Student("xiaohong");
console.log(stu.hasOwnProperty("name")); //name
console.log(stu.hasOwnProperty("say")); //false
console.log(stu.hasOwnProperty("speak")); //false
isPrototypeOf 检查一个对象是否存在于另一个对象的原型链上
function Student (name){
this.name = name;
}
Student.prototype.say = function(){
alert(this.name);
}
var stu = new Student("xiaohong");
console.log(Student.prototype.isPrototypeOf(stu)) // true
console.log(Function.prototype.isPrototypeOf(stu)) // false
console.log(Object.prototype.isPrototypeOf(stu)) // true
注意事项
1.改写面向对象程序,要让所有函数不能嵌套;
2.提取变量,让函数正常运行;
3.改写面向对象,将方法写在prototype上;
4.注意this指向问题。
对象的三大特点(封装、继承、多态)
封装:
1、写对象
2、用对象
把一些相关的对象和属性放到一起即封装到一起,用一个变量抽象出来,那么这就完成了这个对象的封装
继承:
子对象可以使用父对象的一些属性和方法
多态:又分为重载 和 重写
重载就是根据不同的参数类型,参数个数实现不同的功能
重写就是父类的方法不好用,我自己重新定义一个方法名相同的不同方法(方法名相同但方法体不同)