回想自己已经工作了有一段时间了,但是自己对JavaScript的原型链、和继承的理解能力没有到位,最近他们彻底的整理并且复习了一遍。

本案例中部分文案来自网络和书籍,如有侵权请联系我,我只是把我的理解和想法告诉大家。

本着互联网分享精神、现在我就将我的学习以及理解分享给大家。如果那里又说的不对的地方请私信我,我会及时回复。

创建一个构造函数- 案例一

讲解:很多人见到了久违的new操作符,于是就叫Person为“类”,可是又没有关键字class的出现,觉得叫“类”有点勉强。于是退而求其次叫Person为类的构造函数。这些概念好像都没有错,之所以出现这样的情况,可能是因为大家都学习了传统的面向对象语言(c++,c#,Java等),还有一种思维定势吧。为了让javascript也面向对象,要在javascript中找到与传统面向对象语言的影子。可是按照javascript的说法,function定义的这个Person就是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。

function Person(name) {
this.name = name;
this.showMe = function () {
console.log(this.name);
}
}; var per= new Person('铅笔') //实例化这个构造函数 per.showMe() //执行函数内部的方法

prototype讲解- 案例二

讲解:在上面的案例中已经说到了,function定义的函数是一个特殊对象,他拥有prototype属性。prototype属性可以在对象的原型中添加原型方法。

请看代码

function Person(name) {
this.name = name;
this.showMe = function () {
console.log(this.name);
}
};
Person.prototype.user = function (user) { // 向原型中添加原型方法
return user
};
Person.prototype.age = 23; // 像原型中添加属性,并且赋值,
var one = new Person('js'); // 实例化方法。 console.log(one.user('这是原型对象')); //调用实例化方法的方法
console.log(one.age); //调用实例化方法的属性

案例二的代码中,为什么可以调用Person的pertotype方法呢。这就要讲到Peron在实例化时候发生的事情。

第一件事情:建立了一个one对象。(可以理解为 var one={})

第二件事情:将one对象的内置原型对象(__proto__)设置为构造函数person的prototype属性所引用的那个原型对象。(可以理解为:one.__proto__ = Person.prototype; 这个__proto__稍后再讲)

第三件事:将one对象作为this参数调用构造函数person(可以理解为var one={ Person.call(this}; 也就相当于当前对象拥有了Person中所有的属性和方法)

这样就可以理解为什么one可以直接调用proson的pertotype方法了。

constructor讲解-案例三

在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身(Person)。

function Person(name) {
this.name = name;
this.showMe = function () {
alert(this.name);
}
}; var one = new Person('js');
alert(one.prototype)//undefined
alert(typeof Person.prototype);//object
alert(Person.prototype.constructor);//function Person(name) {...};

以上三案例是不是看着有点晕了,其实没那么复杂,直接上图。

__proto__原型链讲解-案例四

在案列二中讲到每一个函数都有一个protytype属性,而对象却没有,但是对象有一个__propt__内置属性,并且这个属性是包含对指定对象的内部原型的引用。原型链上的对象正是依靠这个__proto__属性连结在一起的。注意函数本质也是对象而且是特殊对象,所以函数也有__propt__属性。

function Person(name) {
this.name = name;
this.showMe = function () {
console.log(this.name);
}
}; Person.prototype.from = function () {
console.log('I come from prototype.');
} var per = new Person('js');
console.log(per.__proto__) //输出 Person { from: [Function] }

在举一个原型链的例子

var Person = function() {};
Person.prototype.say = function() {
console.log("Person say");
};
Person.prototype.salary = 50000; var Programmer = function() {};
Programmer.prototype = new Person();
Programmer.prototype.writeCode = function() {
console.log("Programmer writes code");
}; var p = new Programmer();
p.say(); // Person say
p.writeCode(); // Programmer writes code
console.log(p.salary); //
console.log(p.__proto__) // Person { writeCode: [Function] }
console.log(p.__proto__.__proto__) //Person { say: [Function], salary: 50000 } 看沒看到,这里才有salary和say方法 这就是原型链,直到找到这个方法为止。
console.log(p.__proto__.__proto__.__proto__) // {} __proto__会一直向上查找,直到{}才会停止,此刻就会证明没有找到方法或属性。到头了呀亲、

原型链上图。唉图画的好累啊。

在举一个修改__proto__指向的例子

function Person(name) {
this.name = name;
this.showMe = function () {
console.log(this.name);
}
}
Person.prototype.from = function () {
console.log('I come from prototype.');
};
function SubPer() {
this.tests = function () {
console.log('tst')
}
}
var son = new SubPer();
console.log(son.__proto__); //SubPer {}
son.tests();
// son.from() //此刻会报错
son.__proto__ = new Person('name'); //修改son实例对象的prototype原型对象的引用
console.log(son.__proto__); // Person { name: undefined, showMe: [Function] }
son.showMe() //name
son.tests(); //此方法会被调用,因为SubPer函数内自身就有 tests 函数。
son.from(); //此刻会调用Person原型对象方法,因为更改了son实例对象的prototype原型对象的引用。

使用hasOwnProperty判断属性是自身的还是原型链上的。

在JavaScript的对象中有这样一个神奇的方法hasOwnProperty,他可以判断该方法或属性是对象自身的还是原型链上的,废话不多说直接上代码。

function a(name) {
this.name = name;
this.showName = function () {
console.log(this.name)
}
}
function b(name) {
this.name = name;
this.showName = function () {
console.log(this.name)
}
}
b.prototype.say = function () {
return 'say'
};
var cat = new b('123456');
cat.user = '铅笔';
cat.showName();
console.log(cat.hasOwnProperty('showName')); //true showName方法是构造函数b内的方法,cat对象是通过实例化b得到的。在实例化b的时候会有这么一步 b.call(cat,'123456'); 所以返回true
console.log(cat.hasOwnProperty('say')); //false say属于cat内置原型对象(__propo__)指向原型链的方法,不算自身的方法,
console.log(cat.hasOwnProperty('user')); //true 虽然属性是在new 后加的,但是也算是对象的属性呀,所以返回的ture

那么如果对象中包含haoOwnProperty怎么办。-终极方案

function a(name) {
this.name = name;
this.showName = function () {
console.log(this.name)
}
}
function b(name) {
this.name = name;
this.showName = function () {
console.log(this.name)
}
}
b.prototype.say = function () {
return 'say'
};
var cat = new b('123456');
cat.hasOwnProperty = function () {
return true
};
cat.user = '铅笔';
cat.showName();
console.log(cat.hasOwnProperty('啦啦啦')) // true
console.log(({}).hasOwnProperty.call(cat, ('啦啦啦'))); // false 此刻只能采用终极方案,

JavaScript的原型链继承__propt__、prototype、constructor的理解、以及他们之间相互的关系。的更多相关文章

  1. JavaScript各种继承方式(一):原型链继承(prototype chaining)

    一 原理 子类的构造函数的原型对象,是父类的构造函数创建的实例. function Fruit(){ this.name = '水果'; this.nutrition=['维生素','膳食纤维']; ...

  2. 深入浅出JavaScript之原型链&继承

    Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...

  3. 🍓JavaScript 对象原型链继承的弊端 🍓

  4. javascript中继承(一)-----原型链继承的个人理解

    [寒暄]好久没有更新博客了,说来话长,因为我下定决心要从一个后台程序员转为Front End,其间走过了一段漫长而艰辛的时光,今天跟大家分享下自己对javascript中原型链继承的理解. 总的说来, ...

  5. JavaScript之原型链与原型链继承

    原型链 定义:每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype).该原型对象也有一个自己的原型对象(__proto__),层层 ...

  6. 原型链继承中的prototype、__proto__和constructor的关系

    前不久写了有关原型链中prototype.__proto__和constructor的关系的理解,这篇文章说说在原型链继承中的prototype.__proto__和constructor的关系. 通 ...

  7. 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)

    上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...

  8. javascript原型链继承

    一.关于javascript原型的基本概念: prototype属性:每个函数都一个prototype属性,这个属性指向函数的原型对象.原型对象主要用于共享实例中所包含的的属性和方法. constru ...

  9. Javascript 组合继承 原型链继承 寄生继承

    Javascript继承通常有三种方式. 第一种:组合式继承: function SuperType(name) { this.name = name; this.colors = ["re ...

随机推荐

  1. Enabling Remote Errors in SSRS

    January 18, 2011 By default the remote errors property in SQL Server Reporting Services is set to fa ...

  2. 未能加载文件或程序集“ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf116

    最近项目新增需求批量通过Excel导入数据,果断想到NPOI,结果导入的时候突然跳出 未能加载文件或程序集“ICSharpCode.SharpZipLib, Version=0.86.0.518, C ...

  3. WordPress插件Social Warfare<=3.5.2 无需登录RCE漏洞

    该漏洞只存在于Social Warfare插进的3.5.0.3.5.1和3.5.2版本中,其他版本不存在. 2019年3月21日插件作者紧急发布了3.5.3版本以修复高危的RCE漏洞,在<=3. ...

  4. Python----初次见面,请多关照!

    1.计算机的最基本认识 CPU(大脑) 3GHZ + 内存(DDR4) + 主板 + 电源(心脏)+ 显示器 + 键盘 +鼠标+ 显卡 + 硬盘 80MB/s 操作系统分为: windows 家用 l ...

  5. Requests Header | Http Header

    Requests Header | Http Header Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accep ...

  6. css编写规范最佳实践

    最初,在编写CSS的时候,我们往往想到哪儿就写到哪儿,它们之间的关联性和有序性并不在考虑之中.但随着代码量的增加,亦或是多人共同开发,CSS的编写规范变得重要起来了.本文通过三个方面,总结出CSS编写 ...

  7. Hadoop虚拟机的jdk版本和本地eclipse的版本不一致怎么办

    在本周学习Hadoop遇到了一个问题,困扰了半天,本人在安装Hadoop时是按照视频来的,结果发现Hadoop上的jdk版本和本地eclipse的版本不一致,导致本地的程序到处jar包传到虚拟机上运用 ...

  8. 编程开发之--java多线程学习总结(3)类锁

    2.使用方法同步 package com.lfy.ThreadsSynchronize; /** * 1.使用同步方法 * 语法:即用 synchronized 关键字修饰方法(注意是在1个对象中用锁 ...

  9. Web服务器与浏览器的实现原理

    Web服务器与浏览器的实现原理 第一部分 为什么会出现web程序? 单机程序不能共享功能的特性导致了客户机服务器模式的诞生  有一台服务器有特定功能的程序 其他计算机通过客户端程序与服务器交流间接使用 ...

  10. Sci-Hub

    提到Sci-Hub这个文献下载利器,大家肯定都不陌生.你在各大SCI杂志上看到的英文文献,90%以上都能免费下载.因为它严重侵犯了爱思唯尔.施普林格.Wiley等各大出版商的利益,遭到起诉与封杀. 不 ...