JS-面向对象(构造函数、原型)
什么是面向对象?
对象的本质:属性和方法的集合
学过的对象
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");
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();
原型
![](https://img.haomeiwen.com/i15859737/d8659a4ce2872ad0.png)
原型是函数的伴生体
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法
prototype(原型)属性指向的对象就是原型对象
js中万物皆对象,因此原型也是对象,可以通过原型实现对象属性的继承
<script>
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);
</script>
几个必记的属性和方法
-
constructor prototype里面的constructor指向当前对象的构造函数
-
proto === [[prototype]] 指向父类的prototype
-
prototype 指向当前对象的原型对象
-
instanceof 运算符,判断当前对象是否是另一个对象的实例
<script>
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);
</script>
- hasOwnProperty 判断对象上是否存在某个属性,并且这个方法会过滤到原型上的属性
<script>
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
</script>
- isPrototypeOf 检查一个对象是否存在于另一个对象的原型链上
<script>
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
</script>
1.改写面向对象程序,要让所有函数不能嵌套;
2.提取变量,让函数正常运行;
3.改写面向对象,将方法写在prototype上;
4.注意this指向问题。
对象的三大特点
封装、继承、多态
抽象:抽出和问题相关的东西
封装:
1、写对象
2、用对象
把一些相关的对象和属性放到一起,用一个变量抽象出来,那么这就完成了这个对象的封装
继承:
子对象可以使用父对象的一些属性和方法
多态:重载,重写
重载就是根据不同的参数类型,参数个数实现不同的功能
重写就是父类的方法不好用,我自己重新定义一个方法名相同的不同方法
this
this是js的关键字
他是根据执行上下文(执行环境)动态指向当前调用的对象;
谁调用,就指谁
// 1,全局this指window
console.log(this); // window
function foo() {
console.dir(this);
}
// 2,全局函数的this也指window
foo(); // window
// 3,事件处理函数this指事件触发对象
document.body.onclick = foo; // body
// 4,对象方法里的this 指对象本身
var obj = {foo}; // {foo: foo}
obj.foo(); // obj
// 4.1, 谁调用就指谁
var obj1 = {};
obj1.foo = obj.foo;
obj1.foo(); // obj1
var obj2 = {};
//5,匿名函数的this指window
(obj2.foo = obj1.foo)(); // window
(obj2.foo)();
function () {
// this window
obj2.foo(); // obj2
}