浅谈面向对象和继承
Posted lianqing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈面向对象和继承相关的知识,希望对你有一定的参考价值。
1.面向对象和面向过程的区别
面向过程:注重代码的过程
面向对象:注重代码的结果
2.面向对象三大特性
抽象 封装 继承 多态(JS不存在多态)
3.什么是一个构造函数
new 一个关键字函数 创建一个对象,该对象的的属性this指向window 函数里面指向这个对象
构造函数和普通函数的区别 :
1、前者的this的指向是实例化后的对象 后者的指向是指向window
2、普通函数返回值需要加return 构造函数不需要因为返回的是自己本身
为什么构造函数没有return却能够有返回值呢?
因为构造函数在调用的时候系统内部 自动return出了一个this,而这个this就是指的这个对象
这是就不得不说下this的指向问题了
this的指向调用它的对象(可以通过bind/apply/call来改变this的指向)
1.严格模式下this的指向为undefined
2.一个对象 属性this指向window 方法里面的指向为这个对象
3.异步事件this的指向为调用它的对象
计时器为window
ajax也为window
4.箭头函数中的this
此时的 this继承自obj, 指的是定义它的对象obj(也可以理解为它外层的指向就是它的指向), 而不是 window,里面只要还是箭头函数就一直是obj 而不是window 如若不是则是window(会继承下来)
var obj={ say:function(){ un=()=>{ console.log(this) //obj cn=function(){ console.log(this)//window } cn() dn=()=>{ console.log(this) //obj } dn() } un() } } obj.say()
var obj={ say:function(){ setTimeout(()=>{ console.log(this) //obj }); (function(){ console.log(this) //window })() setTimeout(function(){ console.log(this) //window
}) } } obj.say()
这里要注意输出顺序函数声明提升
5.箭头函数和普通函数混用
var obj = { say: function () {
console.log(this) //obj un=function(){ console.log(this) //没有宿主对象,默认是window setTimeout(()=>{ console.log(this) //定义它对象的obj是window }) } un() } } obj.say()
6.严格模式下的混用
箭头存在其中依然是undefinde
严格模式下,没有宿主调用的函数中的this是undefined!!!所以箭头函数中的也是undefined!
继承:
call和apply一般情况下我们都是用来做属性继承的。
第一个参数都是 this的指向
call第二个参数为一系列的值
apply第二个参数为一个数组
Object.prototype.toString.call():检测一个复杂数据类型是一个什么样的类型
instanceof:判断一个对象是不是另一个对象创建出来的
typeof:只能判断基本数据类型 引用数据类型统计返回OBject
原型:
prototype:
每一个函数里面都有一个prototype属性 这个属性叫做原型 这个原型指向一个对象 我们把这个对象叫做原型对象
1、节约内存
2、扩展属性和方法
3、实现类的继承
原型对象里面有2个东西
constructor:构造器-->作用指向创建自己的那个构造函数
__proto__:__proto__属性指向的是创建自己的那个构造函数的原型
1、每一个对象里面都会有一个__proto__这个属性
2、__proto__指向了一个对象 这个对象是原型对象
3、实例化对象可以直接访问__proto__里面的一些方法
new person).__proto__==person.prototype
原型链:
什么叫做原型链?
原型链:由__proto__形成的链条
Object里面的__proto__指向的是null 原型链的顶点
方法继承:后面改变在加会影响到前面的(引用传递)
1.原型继承 Man.prototype = Person.prototype 缺点:污染父级
function person(name,age) { this.name=name this.age=age }
person.prototype.eat = function(){
}
person.prototype.sleep = function(){
}
function man(sex){ this.sex=sex } console.log([person]) man.prototype=person.prototype man.prototype.work = function(){}; p1=new man() console.log(p1,[person])
2.原型拷贝:for(var attr in person.prototype){
man.prototype[attr]=person.prototype[attr]
}
function person(name,age) { this.name=name this.age=age } person.prototype.eat = function(){ } person.prototype.sleep = function(){ } function man(sex){ this.sex=sex } console.log([person]) for(var key in person.prototype){ man.prototype[key] = person.prototype[key]; } man.prototype.work = function(){}; p1=new man() console.log(p1,[person])
缺点:假设Person上面还有父级 那么我们的Man是无法访问到Person父级的原型上的方法
3.原型链继承(Man.prototype = new Person())
多了东西少了东西
person.prototype==new man.__proto__.__proto__
function person(name,age) { this.name=name this.age=age } person.prototype.eat = function(){ } person.prototype.sleep = function(){ } function man(sex){ this.sex=sex } console.log([person]) man.prototype=new person() man.prototype.work = function(){}; p1=new man()
4.混合继承:少了contructor 原型对象的指向也发生改变 而且还无缘无故多了好多东西
man.prototype = {
constructor:man,
//原型链继承
__proto__:person.prototype
}(因此改善)
5.寄生继承(间接继承)
利用的是原型链继承的基础
function fn(){}
继承空的方法
fn.prototype=person.prototype
因为它是纯净的只有里面的方法 不能直接Man.prototype = new fn() 这样也会污染
Man.prototype = new fn()
少了contructor 原型对象的指向也发生改变 而且还无缘无故多了好多东西
改善(加contructor)
不能做到函数复用
以上是关于浅谈面向对象和继承的主要内容,如果未能解决你的问题,请参考以下文章