一切都是对象!

  以下的四种(undefined, number, string, boolean)属于简单的值类型,不是对象。剩下的几种情况——函数、数组、对象、null、new Number(10)都是对象。他们都是引用类型。

  判断一个变量是不是对象非常简单。值类型的类型判断用typeof,引用类型的类型判断用instanceof。

var fn = function () { };
console.log(fn instanceof Object); // true

  java中的对象都是new一个class出来的,而且里面有字段、属性、方法,规定的非常严格。但是javascript就比较随意了,数组是对象,函数是对象,对象还是对象。对象里面的一切都是属性,只有属性,没有方法。那么这样方法如何表示呢?方法也是一种属性。因为它的属性表示为键值对的形式。而且javascript中的对象可以任意的扩展属性,没有class的约束。

  在javascript中,一切(引用类型)都是对象,对象是属性的集合。


一切对象都是通过函数创建的!

譬如:

var obj = {a: 1, b: 2},
var mm = {12, 'X', false} 

实质上的本质为:

var obj = new Object();
  obj.a = 1;
  obj.b = 2; var mm = new Array();
  mm[0] = 12;
  mm[1] = X;
  mm[2] = false;

其中的Object和Array都是函数。

上面的写法其实是下面写法的一种"便捷方式"。


原型 prototype

  !每一个函数都有一个默认属性“prototype”。

  前面说过,每一个函数都是一种对象,都是属性的集合,你可以对函数进行自定义属性。Javascrpit默认给每一个函数一个默认属性---prototype。

  这个prototype的属性值是一个对象(属性的集合),默认的只有一个叫做constructor的属性,指向这个函数本身。

  

  当然,prototype作为一个对象,属性的集合,也可以自定义的增加许多属性。

function Fn() { }
Fn.prototype.name = 'Tom';
Fn.prototype.getYear = function () {
return 1988;
};

隐式原型 _proto_  

  !每一个对象都有一个隐藏的属性“_proto_”,这个属性引用了创建这个对象的函数的prototype。即:fn.__proto__ === Fn.prototype.

  这里的"__proto__"称之为“隐式原型”。

  

  在上面的这张图中可以看出来,自定义函数Foo.__proto__指向Function.prototype,Object.__proto__指向Function.prototype。Function也是一个函数,函数是一种对象,也有__proto__属性。既然是函数,那么它一定是被Function创建。所以——Function是被自身创建的。所以它的__proto__指向了自身的Prototype。

  每个对象都有一个__proto__属性,指向创建该对象的函数的prototype。而每个函数的prototype也是一个对象,他同样有一个_proto_属性,其本质上与var obj = {} 是一样的,都是被Object创建,所以它的__proto__指向的就是Object.prototype。

  而Object.prototype的_protype属性比较特殊,它指向的是一个null值。

typeof & instanceof

  对于值类型,你可以通过typeof判断,string/number/boolean都很清楚,但是typeof在判断到引用类型的时候,返回值只有object/function,你不知道它到底是一个object对象,还是数组,还是new Number等等,这个时候就需要用到instanceof。

  

  Instanceof运算符的第一个变量是一个对象,暂时称为A;第二个变量一般是一个函数,暂时称为B。

  Instanceof的判断队则是:沿着A的__proto__这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。

  比如:

console.log(Object instanceof Function);
console.log(Function instanceof Object);
console.log(Function instanceof Function);

  结果都为true。

  而如何理解instanceof的作用呢?

  其实instanceof表示的就是一种继承关系,或者原型链的结构。


继承 & 原型链

  “继承”是常用面向对象语言中最基本的概念,但是java中的继承与javascript中的继承又完全是两回事儿。

  javascript中的继承是通过原型链来体现的。

  如下面的代码:

function Foo() {};
var f = new Foo();

f.name = 'Cat';
Foo.prototype.name = 'Tom';
Foo.prototype.sex = 'Man' console.log(f.name);
console.log(f.sex);

  结果:

  访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链。

  在上例中,访问f.sex时,f的基本属性中没有sex,于是沿着__proto__找到了Foo.prototype.sex。

  我们在实际应用中如何区分一个属性到底是基本的还是从原型中找到的呢?答案是——hasOwnProperty。譬如: if (f.hasOwnProperty(X)){}。

  而问题又出来了,在f中是没有hasOwnProperty这个方法的,那这个方法是从哪里来的呢?

  其实他是从Object.prototype中得到的。对象的原型链是沿着__proto__这条线走的,因此在查找f.hasOwnProperty属性时,就会顺着原型链一直查找到Object.prototype。

  由于所有的对象的原型链都会找到Object.prototype,因此所有的对象都会有Object.prototype的方法。这就是所谓的“继承”。


ps:

  如果继承得到的方法感觉不合适,你可以自己进行修改。

  如果继承无法满足需要,还可以自己添加方法。不过如果你要添加内置方法的原型属性,最好做一步判断,如果该属性不存在,则添加。如果本来就存在,就没必要再添加了。

【Javascript】Javascript原型与继承的更多相关文章

  1. 【面试必备】javascript的原型和继承

    原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...

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

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

  3. javascript的原型和继承(1)

    原型与继承是javascript中基础,重要而相对比较晦涩难解的内容.在图灵的网上看到一篇翻译过的文章,有参考了一些知名博客.我自己总结了几篇.通过这次的总结,感觉自己对原型和继承的认识又增加了很多, ...

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

    回想自己已经工作了有一段时间了,但是自己对JavaScript的原型链.和继承的理解能力没有到位,最近他们彻底的整理并且复习了一遍. 本案例中部分文案来自网络和书籍,如有侵权请联系我,我只是把我的理解 ...

  5. JavaScript 面向对象 原型(prototype) 继承

    1.对象的概念:无需属性的集合,属性可以为数值,对象或函数,ECMAscript中没有类的概念,这点是javascript与其他面向对象(OO)语言不同的地方. //创建一个自定义对象 var per ...

  6. JavaScript基于原型的继承

    在一个纯粹的原型模式中,我们会摒弃类,转而专注于对象,基于原型的继承相比基于类的继承的概念上更为简单 if( typeof Object.beget !== 'function') { Object. ...

  7. javascript的原型与继承(2)

    这是上一篇的后续. Javascript是一种基于对象的语言,遇到的所有东西几乎都是对象.如果我们想要把属性和方法封装成一个对象,应该怎么做呢: 假设我们把猫看成一个对象: var Cat = { n ...

  8. javascript高级:原型与继承

    原型继承的本质就是一条原型链,对象会沿着这条链,访问链里的方法属性. 对象的__proto__属性就是用于访问它的原型链的上一层: 考虑以下对象: 1. 所有对象的原型: Object.prototy ...

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

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

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

随机推荐

  1. delphi sqlsever 实现存在则更新,不存在

    (' if exists(select * from NBcommission where Type='''+sType+'''and ItemNo='''+s+''' ) '+ ' begin'+ ...

  2. java学习(二)运算符

    一.运算符 赋值运算符:=  +=  -=  *=  /=  %= 算术运算符:+ - *  /  %   ++   -- int x = 3;  int y = 4   int c = x*1.0 ...

  3. 前台通过form表单向Django后台传输数据,Django处理后返回给前台

    摘要:Django前后台数据传递 通过action将数据传输给apitest这个地址,使用get方法传递,此处需要传递name="request_method"的下拉列表值和nam ...

  4. 通过api获取句柄控制其他窗体

    很多时候,编写程序模拟鼠标和键盘操作可以方便的实现你需要的功能,而不需要对方程序为你开放接口.比如,操作飞信定时发送短信等.我之前开发过飞信耗子,用的是对飞信协议进行抓包,然后分析协议,进而模拟协议的 ...

  5. 2018.11-2019.1的随记|NOIP的考后随记

    就是日记吧?(这里就是写一些乱七八糟的东西qwq,当作自己的零散想念吧 1.24 今天跟着BLUESKY他们的视频一起领略了一下远在广州的CCF冬令营开幕式,看着ljh的拍的照片也体验了一下RM冬令营 ...

  6. linux命令之磁盘与文件系统管理命令(上)

    1.fdisk:磁盘分区工具 该命令是linux下常用的磁盘分区工具,但是只能给小于2TB的磁盘划分分区. 常用参数为-l,显示所有磁盘分区的信息. 示例: 1)显示磁盘分区列表 [root@boxi ...

  7. drf序列化器serializers.SerializerMethodField()的用法

    问题描述: 为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢? 解析: 带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request, ...

  8. 【BZOJ1055】[HAOI2008]玩具取名(区间DP)

    [HAOI2008]玩具取名 题目描述 某人有一套玩具,并想法给玩具命名.首先他选择\(WING\)四个字母中的任意一个字母作为玩具的基本名字.然后他会根据自己的喜好,将名字中任意一个字母用" ...

  9. React.Children详解

    React.Children提供了处理this.props.children的工具,this.props.children可以任何数据(组件.字符串.函数等等).React.children有5个方法 ...

  10. 2018年10月19 手记 - 身为开发者的我de窘境

    从10月1国庆过完节回来,那已经是7号了,之后便开始紧锣密鼓的筹划着接下来11月份的公司组织的对外活动,这边新来的产品对产品或者说对任务很是负责,并且策划了很多的方案,并且乐意站在我们开发的角度上去考 ...