原型的引入
通过之前的对象创建方法,没办法解决实例对象之间数据共享问题,所以引入原型。构造函数-原型对象-实例对象的关系如下图:
简单的原型语法
原型中的方法是可以相互访问的
function Sdudent(name,age,sex){
this.name=name;
this.age=age;
thsi.sex=sex;
}
// 原型最朴素的写法,缺点太零散
Student.prototype.height="188";
Student.prototype.weight."55kg";
Student.prototype.study=function(){
console.log("学习,写500行代码,小菜一碟");
};
Student.prototype.eat=function(){
console.log("吃了一个大西瓜");
};
// 简单的原型写法,相对有 结构感
Student.prototype={
constructor:Student,
height:"188",
weight:"55kg",
study:function(){},
eat:function(){}
};
实例对象使用的属性和方法层层的搜索
实例中使用的属性或者方法,先在实例中查找,找到直接调用,找不到则去实例对象中的_proto_指向原型对象prototype中找。
局部变量变成全局变量
如果说原型对象解决了同对象不同实例间数据共享问题,那么怎么去解决不同对象之间的数据传递,采用全局变量可以解决这个问题。
(function ( win ) {
var num=10; //局部变量
win.num=num; // Js是一门动态类型语言,对象没有属性,点了就有了
})(window);
console.log(num);
面向对象思想
根据需求,抽象出相关对象,总结对象特征和行为,把特征变为属性,把行为变成方法。然后定义JS构造函数,实例化对象,通过对象调用属性和方法,完成相应的需求。
- js不是面向对象的语言,是一门基于对象的语言,模拟面向对象
- 面向对象的特性:封装、继承、多态
- 封装:就是包装
1、一个值存储在一个变量中–封装
2、一坨重复代码放到一个函数中—封装
3、一系列的属性放到一个对象中—封装
4、一些功能类似的方法(函数)放在一个对象中—封装
5、好多相类似的对象放到一个JS文件中—封装 - 多态:一个对象有不同的行为,或者同一个行为针对不同的对象。js可以模拟多态,但是实际中不用
- js通过构造函数来模拟oop的类class,通过原型实现继承
原型链
是一种关系,实例对象和原型对象之间的关系,关系是通过原型(proto)来联系的。
- 构造函数中的this就是实例对象
- 原型对象中方法中的this就是实例对象
- 原型指向可以改变
1、实例对象的原型_proto_指向的是该对象所在的构造函数的原型对象
2、构造函数的原型对象prototype指向如果改变了,实例对象的原型_proto_指向也会发生改变。
- 原型链最终的指向是Object的prototype中的__proto__是null
- 如果原型指向改变了,那么就应该在原型改变之后添加原型方法。
apply和call方法
作用:可以改变this的指向,函数可以指向参数中的对象,让参数中的对象拥有该函数。
function Person(age,sex) {
this.age=age;
this.sex=sex;
}
Person.prototype.sayHi=function (x,y) {
console.log("您好啊:"+this.sex);
return 1000;
};
function Student(name,sex) {
this.name=name;
this.sex=sex;
}
var r1=per.sayHi.apply(stu,[10,20]); //sayHi()函数为stu对象所有
var r2=per.sayHi.call(stu,10,20);
所有函数都是Funcion对象实例,apply和call方法属于Funcion原型对象prototype.