Javascript讲解系列之一 Prototype原型链

以前没有写博客的习惯,许多的技术积累都是自己稍微总结一下,很少共享,并非自私,而是工作比较忙,前几天接到一个电话面试不理想,才发现公司所用的DOJO并不被外面广泛接受,故而决定把自己所学分享出来,为夯实基础,也为与外界交流思想,形成一种渠道,如需联系,请发送至邮箱:[email protected]。

今天写Javascript系列之第一篇:Prototype原型链。在软件园里随便拉一个码农估计都会写JS,大部分也知道JS是基于原型的语言,但是如果问及JS原生对象(Object,Function,Array,Date等)的这个原型链长什么样子?估计能回答出来的人就少了,我开始也非常糊涂,后来决心一定要好好搞一下,花了2天功夫基本算是明白了,分享如下:

测试环境:Firefox、Firebug;

为做好铺垫,按顺序解释如下概念:

1)类型、原生类型、对象类型(types、primitive types、object
types)

不像我们在学习JAVA时,被告知JAVA是完全OOP的语言:class是一类具有共同特点的物体的抽象,object是某个class下具体的一个实例,Object类是所有类的顶层父类,对Java的认知是从类与对象开始的;Javascript则不然,它是从类型(type)开始,在各类语言中遇到的number,string,
boolean, object, function,array等都属于类型。

这些类型在JS中分为两大类:原生类型与对象类型,原生类型包括:number,string, bool, null,
undefined;剩下的非原生类型对象都属于对象类型,包括:object, array,
function等,这里的object专指具有属性(attribute)的对象,在Firebug中的代码示例如下:


function log(){ console && console.log.apply(console, arguments); };
var opts = Object.prototype.toString;

// 1) primitive types
log(typeof 1); // number
log(typeof ""); // string
log(typeof false); // boolean
log(typeof undefined); // undefined
log(typeof null); // object null是个特列,属于原生类型;
log(null instanceof Object); // false
// 2) object types.
log(typeof new Object); // object
log(typeof new Function); // function
log(typeof new Array); // object

log(opts.call(new Object)); // [object Object]
log(opts.call(new Function)); // [object Function]
log(opts.call(new Array)); // [object Array]

判断某个值是什么大的类型没有意义,往往需要判断它是什么原生类型或者对象类型:判断原生类型,可以使用typeof关键字;判断对象类型,可以使用toString()方法;

2)prototype与__proto__的区别

两者都是对象类型的属性,并非所有的对象类型都有prototype属性,一般只有function对象才有prototype属性(除非主动赋值),它指向的是一个对象,将来会被多个该function的实例所继承(或者说该对象处于多个实例的原型链上);__proto__才是真正的原型链的实际指针,然而许多浏览器并不对外公开这个属性,Firefox暴露出这一属性,仅供开发人员理解,但不推荐开发中使用。下面我们用一段代码来做验证:


// 1) prototype属性:一般只有function对象拥有
log((new Object).prototype); // undefined
log([].prototype); // undefined
log((new Function).prototype); // anonymous {}
// Function, Object, Array是function对象
log(Function.prototype); // function()
log(Object.prototype); // Object {}
log(Array.prototype); // []
// 2) __proto__属性:指向该对象原型链的上一端
log((Object.prototype).__proto__); // null
log((Function.prototype).__proto__); // Object {}
log(Object.__proto__); // function()
log(Function.__proto__); // function()
// function对象Company的prototype属性所指的对象处于实例对象的原型链上
var Company = function(name){
this.name = name;
};
var c1 = new Company("IBM");
var c2 = new Company("Alibaba");
console.log(c1.__proto__ == Company.prototype); // true
console.log(c2.__proto__ == Company.prototype); // true

上面的示例我们确认了__proto__才是原型链中对象之间从下到上的联系的桥梁,那么既然是链总该有个头吧?要是一直找不到头,就成死链了,在JAVA里所有对象都会继承来自最顶层父类Object的方法一样,如:toString方法,JS中会继承哪些方法呢?

3)原型链的最顶端

既然__proto__是链的索引,那么我们是否可以辛苦测试一下常用的对象呢?


// 原型链的顶端
log((Object.prototype).__proto__); // null
log(Function.prototype.__proto__ == Object.prototype); // true
log(Object.__proto__ == Function.prototype); // true
log(Function.__proto__ == Function.prototype); // true
log(Array.__proto__ == Function.prototype); // true
log(Company.__proto__ == Function.prototype); // true
log(Object.__proto__ == Function.prototype); // true
log(Company.prototype.__proto__ == Object.prototype); // true
log(c1.__proto__ == Company.prototype); // true

经过上面的比较后,我们基本就可以画出这个原型链顶端的样子了, 如下图:

4)了解原型链最顶端的意义

意义似乎应该放在前面讲更突出重要性,就当不求甚解吧,个人理解有如下意义:

A) 清楚对象的继承结构,知道它有哪些父类(父类:指的是该对象原型链向上方向的对象);

B) 了解并调用父类的方法,不会混淆功能;

C) 多个对象共享原型链的某一段时,方便调试;

针对A好处,我们可以更好的理解instanceof关键字的作用;

针对B好处,我们可以调用不同父类的方法完全不同的判断需求,比如:Function.prototype.toString.call(obj)方法用于输出function对象的定义代码,Object.prototype.toString.call(obj)方法用于输出该对象所属的object类型;

针对C好处,这个便于理解复杂JS框架中对象的内存管理模型,比如:DOJO框架,这个以后会提及。

刚才我们用__proto__获取原型链,有没有一种通用的方式呢?那么在图中有个方法可以做到:

Object.getPrototypeOf(obj),(未测所有浏览器,Firefox,
IE10可以)。

关于链的样子就讲完了,下期有时间来讲Javascript是否可以模拟OOP;

Javascript讲解系列之一 Prototype原型链,布布扣,bubuko.com

时间: 2024-10-23 10:38:42

Javascript讲解系列之一 Prototype原型链的相关文章

javascript面向对象系列5——知识点(原型和原型链)

基本概念 [原型链]每个构造函数都有一个对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针.那么,如果原型对象等于另一个原型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针.如果另一个原型又是另一个原型的实例,那么上述关系依然成立.如此层层递进,就构成了实例与原型的链条. [原型对象]这个对象包含可以由特定类型的所有实例共享的属性和方法.所有引用类型默认都继承了Object,而这个继承也是通过原型链实现

javascript的oop——>>> [__proto__ 与 prototype/原型链/原型属性与原型方法/for-in循环]

  前  言  OOP  javascript的oop中的__proto__  与  prototype/原型链/原型属性与原型方法/for-in循环 1  __proto__  与  prototype/原型链   1.prototype(函数的原型):函数才有prototype.prototype是一个对象,指向了当前构造函数的引用地址呢.                       2.__proto__(对象的原型对象):所有对象都要__proto__属性.当用构造函数实例化(new)一

打好基础:了解prototype原型链

一.什么是prototype 在创建构造函数时,如果在函数内进行变量声明,声明的将是私有变量,外部无法访问.会使用this来进行实例变量和函数的声明,以保证通过使用该构造函数来声明的对象可以调用这些变量和函数.然而生命实例函数会在每次新建一个对象时都复制一个一模一样的函数到栈空间,十分浪费资源.prototype可以帮助我们解决这个问题,每个构造函数都有一个原型对象,同时都有一个prototype属性,这个属性指向构造函数的原型对象,它被用来实现基于原型的继承和共享.prototype在该变量内

【JavaScript 封装库】Prototype 原型版发布!

1 /* 2 源码作者: 石不易(Louis Shi) 3 联系方式: http://www.shibuyi.net 4 =================================================================================================== 5 程序名称: JavaScript 封装库 Prototype 版 6 迭代版本: 无 7 功能总数: 14 个 8 功能介绍: 9 1. 实现代码连缀 10 2. id /

javascript类继承系列二(原型链)

原型链是采用最主要的继承方式,原理:每一个类(构造器,js中的function)都有一个原型属性(prototype)指向一个原型对象,原型对象有一个构造器(constructor),它又指回到function,是个循环引用,类的每个实例也有一个原型属性(代码无法访问,叫做_proto_),它跟构造器原型指向的是同一个对象,即同一个类的所有实例公用一个原型对象,要实现两个类型的继承,就是将一个类型的原型指向另一个类型的实例,而不再指定原来的默认的原型对象,这样就形成了原型链 子类可以通过原型链获

03. JavaScript高级(3/5)(原型链讲解)

一.原型以及原型链 基础概念: 实例对象的__proto__和构造函数的原型prototype指向相同 实例对象中的__proto__原型指向的是构造函数中的prototype原型 实例对象中的__proto__是原型,是浏览器使用的 构造函数中的prototype是原型,是程序员使用的 实例对象中的proto指向的是构造函数中的prototype所指向的原型对象, 原型链:是一种关系,实例对象和原型对象之间的关系,这种关系是通过实例对象中的原型(proto)来联系的. 改变原型链指向 构造函数

JavaScript 变量、函数与原型链

定义 || 赋值 1-函数的定义 函数定义的两种方式: “定义式”函数:function fn(){ alert("哟,哟!"); } “赋值式”函数:var fn = function(){ alert("切可闹!"); } @页面加载时,浏览器会对JavaScript代码进行扫描,并将 定义式函数进行预处理(类似C等的编译).[函数声明提升] 处理完再由上至下执行,遇到赋值式函数 则只是将函数赋值给一个变量,不进行预处理,待调用时才进行处理. @在定义前面调用函

JavaScript中的继承与原型链

先看一个例子 function User(){} var u1 = new User(); console.log(u1.prototype);// undefined 使用对象实例无法访问到prototype console.log(User.prototype);//{},使用构造函数名访问prototype console.log(u1.__proto__);//{},使用对象实例访问prototype的指针 这个是 __proto__ 和prototype最基本的区别:说明构造的对象无p

JavaScript中的继承(原型链)

一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例