面向对象的三大特点:封装,继承,多态/(重载)
封装:减少代码冗余,提高代码的重复利用率;
继承:子类继承父类的属性 (注释:父类的私有属性和子类的私有属性互不影响,如果子类的私有属性想访问到父类的私有属性,要靠面向对象式:继承)
多态:函数的多种形态(由于js是脚本语言,所以没有多态的说法,但是有重载这一概念,后面会讲到的)
现在我们学习的js是Ecmascript2014(es5)生成对象靠构造函数,但是Ecmascript2015(es6)用class生成类,但是es5是基础;
constructor:构造器
1.浏览器每个类(函数)都有一个prototype的属性,这个属性是一个对象,里面有一个constructor的属性叫构造器,指向当前类的本身;
案例:
function Person(){
this.name="zhang"
}
var a=new Person;
console.log(Person.prototype.constructor==Person) //结果是true 也应证了浏览器每个类(函数)都有一个prototype的属性,这个属性是一个对象,里面有个constructor的属性叫构造器,指向当前类的本身;
2.人为改变类的原型指向(给原型赋值引用数据类型, (注意:基本数据类型不改变))浏览器赋予了constructor的属性就不存在了,可以人为添加如果是简单的基本数据类型constructor还存在;
3.类在代码中扮演者三种角色:普通函数,普通对象,类;
4.每个对象天生有一个__proto__的属性叫原型,它指向父类的原型;
案例:
function Person(){
this.name="zhang"
}
var a=new Person;
console.log(a.__proto__==Person.prototype) //true 每个对象天生一个__proto__的属性叫原型,它指向父类的原型;
5.prototype和__proto__都是原型
前者函数的属性,后者对象的属性
前者给开发者使用(前端程序员),后者浏览器用于查找原型;
对象的继承:
1.克隆对象:不是将一个对象赋值给另一个对象;
var obj1=obj2 这不是对象克隆,是把引用地址赋值给obj1;
怎样才算克隆对象呢:
2.通过for in 和Object.create()的方法拷贝对象
var obj1={
name:"zhang",
age:20
}
var obj2={}
for(var key in obj1){
obj2[key]=obj1[key]
}
console.log(obj2) //通过for in克隆对象 (注意:得到的属性都是私有的)
第二种方法Object.create()的方法拷贝对象
var obj1={
name:"zhang",
age:20
}
var obj2=Object.create(obj1)
console.log(obj2) //通过Object.create克隆对象,(注意:得到的属性都在原型上__proto__(公有的))
this指向问题
this是js的一个关键字,指定一个对象然后代替他
分两种情况:函数内和函数外
函数内的this指向他行为的主体;函数外的this指向window
函数内的this,跟他在哪调用有关,(也就是行为发生的主体)
如何去查找他的主体,就看他有没有带点,如果带点就是点前面的,不带点,this就指向window;
自调用,自执行函数的this指向window
定时器的this指向window;
构造函数的this和原型上的this都是指向他当前实例
给事件绑定一个方法,事件触发时,方法就执行了,this就指向当前对象
6大继承:
1.原型继承: 将父类的私有的,公有的都继承为子类公有的;
案例:
function A(){
this.name="zhang"
}
A.prototype.s=20;
function B(){
this.age=50;
}
B.prototype=new A;
var b=new B;
console.log(b)
2.call继承:将父类的私有的都继承为子类私有的;
案例:
function A(){
this.name="zhang"
}
A.prototype.s=40;
function B(){
this.age=10;
A.call(this)
}
B.prototype.y=1;
var b=new B;
console.log(b)
3.冒充对象继承 将父类的私有的,公有的都继承为子类私有的
function A(){
this.name="zhang"
}
A.prototype.s=10;
function B(){
this.age=1;
var a=new A;
for(var key in a){
this[key]=a[key]
}
a=null;
}
B.prototype.y=50;
var b=new B;
console.log(b)
4.混合继承:将父类的私有的继承为子类私有的,将父类公有的,私有的都继承为公有的;
function A(){
this.name="zhang"
}
A.prototype.s=10;
function B(){
this.age=40;
A.call(this)
}
B.prototype=new A;
var b=new B;
console.log(b)
5.组合继承:将父类私有的继承能够为子类私有的,将父类的公有的继承为子类公有的;
function A(){
this.name="zhang"
}
A.prototype.s=10;
function B(){
this.age=40;
A.call(this)
}
B.prototype=Object.create(A.prototype)
var b=new B;
console.log(b)
6.中间类继承
function fn(){
arguments.__proto__=Array.prototype;
arguments.shift;
console.log(arguments)
fn(12,25,64)
最后的得到的结果为25,64 arguments不是数组,所以他没有array的方法,如果想让他拥有数组的方法,只能用arguments的原型去执行数组的内置类对象原型