构造函数的继承

1. 包装对象

非空对象可以添加属性或者方法

var arr = [];
arr.a = 10;
alert(arr.a);

但是基本数据类型也有自身的方法和属性,这些属性是如何调用的呢?

var str = "abc";
str.charAt(1);

当尝试去调用简单类型的属性或者方法的时候,这个数据类型会找到自身的构造函数身上的属性或者方法,返回查找的属性或方法之后,构造函数自动销毁。这个过程叫做包装对象。

那么上面的字符串调用方法的过程就是这样:

var str = "abc";
str.charAt(1);
str -> str的构造函数 String -> 找到charAt方法并调用 ->销毁这个new String

2.hasOwnProperty

作用:
判断参数是否为自身的私有属性
语法:

obj/fn.hasOwnProperty(属性名);

返回值为Boolean
如果是调用者自身的私有属性,返回true,否则返回false
注意,判断的参数只能是调用者 自身 的私有属性,如果是它的原型或者原型链上的属性也会返回false

function fn1(name){
    this.name = name;
}
fn1.prototype.age = function(){
    console.log(1);
}
var f1 = new fn1('cat');

console.log(fn1.hasOwnProperty('name'));        //true
console.log(fn1.hasOwnProperty('age'));         //false
console.log(fn1.prototype.hasOwnProperty('age'))    //true

3.constructor

作用:
查看某个对象的构造函数是谁

当一个对象实例化之后,浏览器会为它自动加上这个属性。
constructor很容易被修改。当构造函数的原型赋值对象的时候,那么constructor就被修改了,指向Object

这个方法可以手动修正constructor指向(指向正确的构造函数的名称)。

4. instanceof

作用:
这是一个二元运算符
可以用来判断左边的实例化对象是不是右边的构造函数构造出来的
语法:

t2 instanceof t1

t2:实例化对象
t1:构造函数

返回值:
返回一个Boolean,如果t2是t1构造出来的,返回true,否则返回false

5. call,apply

这两个方法都是改变函数中this的指向
语法:

函数名.call(this指向的对象,函数的参数1,函数的参数2,···函数的参数n);

函数名.apply(this指向的对象,[函数的参数1,函数的参数2,···,函数的参数n])

call方法有无限个参数,其中第一个参数是想要个改变的this指向,剩下的参数是函数的实参

apply方法有2个参数,其中给第一个参数是想要改变的那个this指向,第二个参数是一个数组,数组中的每一项数据都是函数的实参

function fn1(a,b){
    alert(a+b);
    alert(this);
}
fn1.call(document,2,3);
fn1.apply(document,[1,2]);

6.继承

6.1 拷贝继承

原理:
属性继承 + 方法继承
如果有一个构造函数init,这个时候需要继承这个init

那么可以创建一个构造函数init2,调用init,修改init2的this指向,这样就可以完成属性继承(使用call或者apply方法)、
那么接下来我们要完成的是方法继承
如果直接让

init2.prototype = init.prototype;

由于构造函数的原型是是一个对象,是引用类型数据。由JS的数据类型的存放我们可以知道,如果这样写,只是把init的prototype的地址指向复制给了init2的prototype,这样如果对init2的prototype进行修改的话,init的prototype也会同步进行修改。因为他们指向的是同一个对象。
所以我们需要使用for··in对init的prototypr进行遍历,逐一取出它的方法赋值给init2的prototype,这样就可以是两个prototype指向不同的对象,两个原型互不干涉。这样就完成了一次拷贝继承。

function Init(){
    this.name = "a";
}
Init.prototype.a = function(){
    console.log("这是原型a");
};

//拷贝继承
function Init2(){
    Init.call(this);
}
for(var attr in Init.prototype){
    Init2.prototype[attr] = Init.prototype[attr];
}
Init2.prototype.b = function(){
    console.log("这回是init2的原型B,Init1没有");
};

var in1 = new Init();
var in2 = new Init2();
in2.a();
in2.b();
in1.b();    //这个会报错

6.2 类式继承

原理:
原型链的查找
现在我们有一个构造函数

function Init(){
    this.name = "init1";
}
Init.prototype.a = function(){
    console.log("这里是init的a方法");
}

如果我们想要继承这个构造函数Init的属性,同时不能使用拷贝继承,那么我们可以使用下面这种方法:
首先创建好这个init2

function Init2(){
    //这里同样需要修改init2的this指向来继承init的属性
    Init.call(this);
}

我们需要创建一个空的函数

function F(){};

然后修改这个函数的原型

F.prototyep = Init.prototype;

然后使用new生成这个F的实例化对象

var objF = new F();

最后,我们把这个实例化对象赋值给Init2prototype,并且手动修正constructor

Init2.prototype = objF;
Init2.constructor = Init2;
//实例化对象,调用
Init2.prototype.b = function () {
    console.log("this is Init2.b");
};
var in2 = new Init2();
var in1 = new Init();
in2.a();
in2.b();
in1.b();        //这个会报错

原理:
使用一个空的构造函数作为桥梁,然后把空的构造函数的实例化对象赋值给需要继承的构造函数,这样,当调用in2的a方法的时候,由于它本身没有a方法,通过__proto__去向上找他的构造函数init2.prototype,但是Init2.prototype = objF这个实例化对象,那么会通过__proto__去向上找他的构造函数FFprototype,但是F.prototype = init.prototype,这样就通过原型链找到了a方法。

in2.a -> objF ->objF.__protot__ -> F ->F.prototype ->init.prototype

这个时候,init.prototype和F.prototype指向同一个对象,init2的prototype和objF指向同一个对象。

6.3 对象继承

如果现在有一个对象obj1

var obj1 = {
    "name":"momo",
    "age":20,
    "say":function(){
        alert(1);
    }
};

利用类式继承的原理,我们可以完美继承这个对象,方法如下

var obj2 = {};
function F(){};
F.prototype = obj1;
var objF = new F;
obj2 = objF;

这个时候调用obj2.say方法,可以alert(1);
给obj2添加新得key也不会影响到obj1
通过原型链的查找顺序为:

obj2.a -> objF ->objF.__proto__ ->F ->F.prototype ->obj1

7 toString

作用:把数据转成字符串。
每个数据类型自身都有toString方法
只要使用alert弹出引用类型的数据,那么就会调用toString方法。

Array.prototype.toString = function () {
    return 'aaa';
};
var arr = [1,2,3];
alert(arr);

但是弹出基本类型就不会调用toString方法

如果为数字类型,那么在toString的括号中写进制,那么就会转成对应的进制结果。(转基数)

var num = 255;
var num2 = "11001000";   //200

console.log(num.toString(2));       //11111111
console.log(parseInt(num2,2));      //200

7.1 判断数据类型

1.typeof

typeof 数据

缺点是没办法判断数组的数据类型

2.instanceof

数据 instanceof 数据类型(构造函数)

3.constructor

数据.constructor

返回一个数据的构造函数,但是这个对于判断ifream中的内容有问题

4.Object.prototype.toString.call(数据)

Object.prototype.toString.call(数据)

这个方法会返回一个[object 数据构造函数];

精确返回,即使在ifream中的数据也没有问题

8.forEach

将一个类数组转换为数组

var boxs = document.querySelectorAll("div");
var boxarr = Array.prototype.slice.call(boxs);
//这样就可以使用forEach来循环类数组啦
boxarr.forEach(function(elem,i){
    elem.onclick = function(){
        alert(i);
    }
});

问题:Object.prototype.toString和Array.prototype.slice这两个都是通过改变this的指向来实现效果,那么Array.prototype.slice的this原来是谁? 是它的实例化对象? 还是window?

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