js面向对象

一、面向对象编程的特点

1.抽象:
2.封装:
3.继承:
4.多态:

二、面向对象的组成

1.对象的属性:对象下面的变量。
2.对象的方法:对象下面的函数。

三、this指向

1.当用new去创建一个对象,构造函数中的this指向新创建出来的对象,而且函数的返回值默认是this(隐式返回)。

四、原型

作用:改写对象下面公用的方法和属性,让公用的方法或者属性在内存中存在一份(提高性能)。

五、包装对象

基本类型都有自己的包装对象:String Number Boolean
当基本类型的对象调用方法时,会先找到对应的包装对象类型,包装对象类型会把对象所有的属性和方法给基本类型,最后包装对象消失。

var str='hello';
str.charAt(0);//e,此处是调用了包装对象String下面的charAt()方法。
var str='hello';
str.number=10;//用包装对象创建对象添加属性
alert(str.number);//undefine,此时包装对象已经消失

六、原型链

1.定义:实例对象与原型之间的连接,叫做原型链。
2.proto(隐式连接)
3.Object对象类型是原型链的最外层

function Aaa(){
    this.num=10;
    }
Aaa.prototype.num=20;
Object.prototype.num=30;
    
var a1=new Aaa();
alert(a1.num);//10
function Aaa(){ }
Aaa.prototype.num=20;
Object.prototype.num=30;
    
var a1=new Aaa();
alert(a1.num);//20
function Aaa(){}
Object.prototype.num=30;
    
var a1=new Aaa();
alert(a1.num);//30
原型链图解

七、面向对象的一些属性和方法

1.hasOwnProperty():查看当前属性是不是对象自身下面的属性。

var arr=[];
arr.num=10;
Array.prototype.num2=20;
alert(arr.hasOwnProperty('num'));//true,arr所独有的属性
alert(arr.hasOwnProperty('num2'));//false,不是arr所独有的属性   

2.constructor:查看对象的构造函数
例1:

function Aaa(){}
var a=new Aaa();
alert(a.constructor);//Aaa

例2:

var arr=[];
alert(arr.constructor);//Array
alert(arr.constructor==Array);//true
arr.constructor==Array可以用于数组类型的判断,但不是最好方法。

注意1:在写完一个函数后,系统会默认给该函数的原型添加一个constructor属性。
例如,创建如下函数:

function Aaa(){}

该函数的原型上默认自动生成一个constructor属性:

Aaa.prototype.constructor=Aaa;

所以有:

function Aaa(){}
var a=new Aaa();
alert(a.constructor);//Aaa

注意2: 系统自带属性for in不能获取到。

function Aaa(){}
Aaa.prototype.name='晓明';
Aaa.prototype.constructor=Aaa;
var a=new Aaa();
for(var attr in Aaa.prototype){
    alert(attr);//可以获取到name,但是不能获取到系统自带的constructor
    }

注意3:避免修改constructor属性。

function Aaa(){}
Aaa.prototype.name='晓明';
Aaa.prototype.age='24';
var a=new Aaa();
alert(a.constructor);//Aaa

如果把上面的属性改写成json的形式

function Aaa(){}
Aaa.prototype={
    name:'晓明',
    age:'24'
    };
var a=new Aaa();
alert(a.constructor);//Object

Aaa.prototype.constructor被改写了!因为Aaa.prototype={};//Aaa.prototype=json,所以Aaa.prototype.constructor==Object。
正确的json写法中应重写constructor属性

function Aaa(){}
Aaa.prototype={
    constructor:Aaa,//json中重写constructor属性
    name:'晓明',
    age:'24'
    };
var a=new Aaa();
alert(a.constructor);//Aaa

八、instanceof:查看对象与构造函数是否在同一条原型链上。

例1:

function Aaa(){}
var a=new Aaa();
alert(a instanceof Aaa);//true,对象a和构造函数Aaa在同一条原型链上
alert(a instanceof Object);//true,对象a和构造函数Object在同一条原型链上

例2:

var arr=[];
alert(arr instanceof Array);//true

arr instanceof Array可用于数组类型的判断,但不是最好方法。

九、toString() :把对象转成字符串

1.系统对象自带toString,自定义的对象都是通过原型链找到Object.prototype的toString。
例1,对于自己写的对象

function Aaa(){}
var a=new Aaa();
alert(a.toString==Object.prototype.toString);//true

例2,对于系统对象

var arr=[];
alert(arr.toString==Object.prototype.toString);//false
alert(arr.toString==Array.prototype.toString);//true

2.toString()的用法
1)把对象转化成字符串。

var arr=[1,2,3];
alert(arr.toString());//'1,2,3'

2)进制转换

var num=255;
alert(num.toString(16));//'ff',将255转化为16进制

3)类型判断
例1,数组

var a=[];
alert(Object.prototype.toString.call(a));//[object Array]

例2,json

var a={};
alert(Object.prototype.toString.call(a));//[object Object]

例3,日期

var a=new Date();
alert(Object.prototype.toString.call(a));//[object Date]

例4,正则表达式

var a=new RegExp();
alert(Object.prototype.toString.call(a));//[object RegExp]

Object.prototype.toString.call(arr)=='[object Array]'可用于数组类型的判断,是最好方法。

拓展:哪种判断数组类型的方法最好呢?
toString方法最好,因为在iframe中创建数组,跨页面时,constructor方法和instanceof方法会失效。

window.onload=function(){
    var oF=document.createElement('iframe');
    document.body.appendChild(oF);
    var ifArray=window.frames[0].Array;
    var arr=new ifArray();//在iframe中创建数组,跨页面
    alert(arr.constructor==Array);//false
    alert(arr instanceof Array);//false
    alert( Object.prototype.toString.call(arr)=='[object Array]');//true
    };

十、对象的继承

1.什么是继承?
1)在原有对象的基础上,略作修改,得到一个新的对象。
2)不影响原有对象的功能
2.拷贝继承(通用型,有new或无new的时候都可以)
1)属性的继承:调用父类的构造函数call
2)方法的继承:for in 拷贝继承(jQuery中采用的也是拷贝继承)

function  Father(name,age){
    this.name=name;
    this.age=age;
    }
Father.prototype.showName=function(){
        alert(this.name);
        };
        
function Son(name,age,job){
    Father.call(this,name,age);//属性继承,用call方法修改this指向
    this.job=job;
    }   
extend(Son.prototype,Father.prototype);//方法继承,采用for in拷贝
//继承。虽然函数是对象,但是函数具有只能重新赋值(开辟新空间,变成新对
//象),不能被修改(在原来空间上修改旧对象)的特点,使它可以通过for in 
//拷贝继承。
Son.prototype.showJob=function(){
    alert(this.job);
    };      
function extend(objson,objfather){
    for(var attr in objfather){
        objson[attr]=objfather[attr];
        }
    }

var person=new Son('晓明','24','学生');
person.showName();//晓明

3.类式继承(适合new构造函数)
利用构造函数继承的方式。
JS中没有类的概念,把JS的构造函数看做类。

Paste_Image.png
function  Father(){
    this.name='晓明';
    }
Father.prototype.showName=function(){
        alert(this.name);
        };      
function Son(){}    

Son.prototype=new Father();//一句话实现继承,但存在很多问题

var s1=new Son();
s1.showName();//晓明
alert(s1.constructor);//Father

存在问题:
1.person.constructor指向Father而不是Son.
这是因为Son.prototype=new Father();这句话重写了Son.prototype,Son.prototype下原有的constructor等属性被覆盖。
解决:修正Son.prototype.constructor,Son.prototype.constructor=Son;
2.子类实例的属性均指向父类中的属性,会相互影响。
解决:属性和方法分别单独继承。

Paste_Image.png

1)创建一个没有属性的空函数F,专门用来继承父类的方法。
2)属性采用call方法继承。
类式继承完整例子:

function  Father(){
    this.name=[1,2,3];
    }
Father.prototype.showName=function(){
        alert(this.name);
        };
        
function Son(){
    Father.call(this);//属性继承,用call方法修改this指向    
    }   
    
//方法继承
var F=function(){};//创建一个没有属性的空函数F,专门用来继承父类的方法。
F.prototype=Father.prototype;
Son.prototype=new F();//一句话实现继承
Son.prototype.constructor=Son;

var s1=new Son();
s1.name.push(4);
s1.showName();//1,2,3,4

var s2=new Son();
alert(s2.name);//1,2,3。属性单独继承后,不同实例的属性相互独立,互不影响。

4.原型继承(适合无new的对象)

var father={
    name:'晓明'
    };
var son=extend(father);
son.name='小强';
alert(father.name);//晓明
alert(son.name);//小强

function extend(obj){
    var F=function(){};
    F.prototype=obj;
    return new F();
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • title: js面向对象date: 2017年8月17日 18:58:05updated: 2017年8月27日...
    lu900618阅读 566评论 0 2
  • 一、面向过程和面向对象的区别、联系 1.面向过程编程:注重解决问题的步骤,分析问题需要的每一步,实现函数依次调用。...
    空谷悠阅读 897评论 1 11
  • 大家好,我是IT修真院深圳分院第01期学员,一枚正直纯洁善良的web程序员。 今天给大家分享一下,修真院官网JS(...
    老菜菜阅读 1,275评论 0 2
  • 学过C++等语言的话,你一定明白面向对象的两个基本概念: 类:类是对象的类型模板,例如,定义Student类来表示...
    Beatrice7阅读 756评论 0 0
  • 人如蝼蚁 众多而忙碌 顿悟 从不跨越是可耻的 而还在沉睡的人里有蝼蚁一个 只是刚处在清醒的状态
    只有经历知道阅读 279评论 0 1