一直搞不懂js的继承机制,虽然知道什么 js继承是由原型prototype和构造函数constructor实现继承!看了很多文章还是这样模糊:为什么这样,为什么那样,为什么为什么为什么!... ... 。不懂为什么,当然就不是真正理解,记也记不住。(即使记住也是没用的)。不过经过自己反复测试后终于茅塞顿开。现拿来和大家分享下。
最难理解的当然就是prototype和constructor,这两个都理解,其他自然不在话下。
prototype:原型prototype方式的属性查询可以理解为js独有的一个机制。
就是说,js读取一个对象属性的时候,对象本身若找不到,则会去读取构造函数的prototype对象的同名属性,然后若还是找不到,则去读取Object构造函数的prototype对象的同名属性——即所谓的“继承”...
如果要实现继承关系A->B,则想要A继承B的属性,则需要自己去维护这个prototype对象。
——这就涉及一些技巧。
constructor:它是每个对象都有的一个属性,它引用初始化这个对象时候的构造函数。js这也是独有的一个机制。它有默认值。
你可以不去维护它,这个时候你不去用它,也不会有任何问题。但是,当你想让它正确工作的时候,则就需要我们去维护它了!
——这就涉及一些技巧。
懂得这两个技巧后,就可以说你理解了js的继承原理!
下面是测试代码,大家测试的时候把相应的地方的注释打开,把不想要的地方注释起来就ok了:
/************ NOTICE START :基础知识 ************ 1 对于函数 每个函数都一个prototype 属性,它引用预定义的原型对象———— prototype在使用new操作符把函数作为构造函数时起作用! —— 具体什么作用呢?后面会讲到 2 对于对象 js中,每个对象都有一个constructor属性,他引用初始化这个对象时候的构造函数 eg. var d = new Date(); d.constructor == Date;// true ———— 注意,这个引用在内建对象时候是自动的,js内部已经维护好了 ================================================================= 但是对于自定义类,则需要自己维护!!! 而在继承的时候可能还会出问题,所以就需要自己修改 ================================================================= 因为自定义类的对象的constructor默认指向Function的构造函数:funciton Function(){ [native code] } 而这可能不是想要的。 所有js的类继承于Object,—— 这其实是js内部做了一些工作实现的 js用原型prototype和构造函数constructor实现继承! ************ NOTICE END ************/ /** * 开始测试 */ //var d = new Date(); //alert(d.constructor==Date);// true //函数 ------ 其实又可当做对象的构造函数 var Person = function(name,age){ this.name = name; this.age = age; this.mc = "MMCC"; this.toString = function (){ return "Person:name="+this.name+"/age="+this.age; }; }; //alert(Person.constructor);// funciton Function(){ [native code] } //alert(Person);// 即上面函数代码 Object.prototype.toString = function(){ return " Object.prototype "; }; //alert(Person.prototype); //显示 [object Object]—— 这是默认的prototype //alert(Object.prototype); //显示 [object Object] //alert(Object); //alert({}); /** * * Man Class Defination. Try to extends the Person Class * @param name * @param age * @param work * @param hobby * @return */ var Man = function(name,age,work,hobby) { this.work = work; this.hobby = hobby; Person.call(this,name,age);// 这样做的目的只有一个:就是借用Person函数初始化name/age。除此之外绝无他意 // 我们可以把这种调用方式叫做构造函数链: 构造函数中调用另一个构造函数 this.toString = function() { return "Man:name="+this.name+"/age="+this.age; }; }; // 注意new Person()这里不需要参数 Man.prototype = new Person();// 这个的意义 ??? //这样之后Man.prototype可以使用Person的方法了!!!———— 对,就是这样的方式,实现了继承!!!———— 当然如果要使用Person的name等属性就会得到undefined //因为 new Person();出来的对象name尽管存在,但未赋值。。。 delete Man.prototype.name;// 可以删去,也可以不删去。影响不是很大。。 //alert(Man.prototype.name); delete Man.prototype.age; //alert(Man.constructor); Person.prototype.wealth = function() { return this.name +" * Person wealth * "+this.age; }; Man.prototype.wealth = function() { return this.name +" * Man wealth * "+this.age; }; Person.prototype.health = function() { return this.name +" * Man health * "+this.age; }; var p = new Person("Chen",25); //alert(p.constructor);// 实际上会去通过原型链的方式查找constructor,最终找到的是类的原型的constructor属性 //alert(p.prototype);// undefined //alert(Person.constructor); // 这个和上面p.constructor结果不同, 它结果为 Function(){ [native code] } __ why var man = new Man("luo",27,"IT","shopping"); //alert(man.constructor);// 实际上会去通过原型链的方式查找constructor,最终找到的是类的原型的constructor属性 //alert(man.prototype);// undefined //alert(Man.constructor); // 这个和上面man.constructor结果不同, 它结果为 Function(){ [native code] } //alert(Man.prototype); //alert(man); alert(man.health()); //alert(p.wealth()); //Man.prototype.constructor = Man;//这样之后,使一个class的constructor属性指向 它的构造函数 --- 这样又有什么好处呢?有什么必要呢? // ———— 使Man类的原型的constructor正确的指向 它的构造函数Man, //这样做的必要性在于,之后我们可能需要“正确”的调用Man函数的constructor属性 //alert(Person.prototype.constructor);// function(name,age){。。。 } //alert(Man.prototype.constructor);// function(name,age,work,hobby) {。。。 } // 下三者都为 true,这是符合继承常理,同时说明子类编写成功 //alert(man instanceof Object);这个想当然是会一直成立的 //alert(man instanceof Person);//这个只有在设置Man.prototype = new Person();才会成立 //alert(man instanceof Man);//这个其实是会一直成立的,不用担心这个 /**============== 单层继承的时候,可以通过为子类原型对象添加一个名为superclass的属性,来简化继承 */ var Man2 = function(name,age,work,hobby) { this.superclass(name,age); this.work = work; this.hobby = hobby; }; //然后在new Man2之前 Man2.prototype.superclass = Person; //然后就可以使用了: var m2 = new Man2("luok",22,"IT","Think"); alert(m2.name); // 一个规则是 一个类的原型的constructor 需要指向 它的构造函数 。 否则呢 // 每个函数都会有一个 prototype 的属性 --- 默认为一个Object的对象,即Object类的实例。 为内建的代码 // 函数的原型对象 // constructor /**可以 直接Man.constructor 、 Man.prototype.constructor 区别:* * Man.constructor 为Man函数的构造函数—— Function(){ [native code]} * Man.prototype.constructor 当然就是Man的原型对象的构造函数 */
总结:
其实js实现继承有多种方式。据说是三种:(一)对象冒充 (二)原型prototype链方式 (即本文介绍的这种) (三)原型prototype拷贝方式
这三种的介绍可以在博文中找到:http://www.iteye.com/topic/70028
不过个人认为,(一)(三)的方式根本不能算是真正的继承。用原型prototype和构造函数constructor实现的继承才是真正的继承。
再次提一下前面讲的两个技巧。相信大家测试后也知道是什么技巧了。这里再说明一下,其实主要就是这两个句:
1——Man.prototype = new Person();
2——Man.prototype.constructor = Man;
相关推荐
此外,underscore.js在实现上还巧妙地利用了JavaScript的原型继承和鸭子类型,使其能够优雅地处理对象。它的`_.extend`函数就是用来实现浅复制的,通过遍历源对象的属性并将其复制到目标对象上。而鸭子类型则是通过...
《Prototype 1.4.0 源码解读:深入理解JavaScript库的基石》 Prototype 是一个著名的JavaScript库,它的1.4.0版本在Web开发领域有着广泛的使用。这个库为JavaScript程序员提供了许多实用的功能,包括对象扩展、类...
在JavaScript中,对象的创建和继承是其面向对象编程的重要组成部分。本文将深入解析这两个概念,并通过示例进行详细说明。 首先,我们来看对象的创建。在JavaScript中,对象可以通过多种方式创建,其中最常见的是...
这个中文手册可能是对ECMAScript标准的详细解读,包括最新的ES6及其后续版本的新特性,如箭头函数、模板字符串、Promise、Generator、Async/Await、模块化(import/export)、类和继承等。此外,还可能涉及错误处理...
JavaScript,通常简称为JS,是互联网上最流行的编程语言之一,尤其在网页开发和前端应用中占据着核心地位。本手册的目标是为初学者提供一个全面的起点,同时也为有经验的开发者提供深入细节的参考。 1. **基础概念*...
### Prototype 1.6.0源码解读 #### 前言 Prototype 是一个轻量级的 JavaScript 库,它简化了 DOM 操作,并提供了一系列便捷的方法来处理对象、数组等基本类型。本文将深入剖析 Prototype 1.6.0 的核心特性与实现...
更不用谈继承、多态了,为了模拟出一些其它面向对象编程语言的这些特性,有好多大牛写了给出了实现方式,看了John Resig的《Simple JavaScript Inheritance》这篇文章,深深被折服了,原来短短几十行javascript也...
4. **面向对象编程**:尽管JavaScript是非严格的面向对象语言,但它支持基于原型的继承和类的模拟,这部分内容会涵盖类与实例、原型链、继承模式(如构造函数、原型链继承、寄生组合式继承等)。 5. **异步编程**:...
总的来说,Prototype 1.4源码解读是一次深入理解JavaScript库设计和实现的好机会,它不仅可以帮助我们提高JavaScript编程技巧,还能让我们更好地理解和应用面向对象编程的思想。在阅读和研究源码的过程中,可以不断...
jQuery 源码解读 jQuery 是一款非常流行的 JavaScript 库,以其简洁的语法和强大的功能深受开发者喜爱。本文将深入探讨 jQuery 的源码结构和执行流程,帮助你更好地理解和运用这个库。 首先,jQuery 的核心架构是...
《prototype.js源码解读》 Prototype.js 是一个广泛使用的 JavaScript 库,它的设计目标是扩展JavaScript的基本功能,提供更丰富的面向对象编程体验。通过阅读和理解Prototype.js的源码,可以深入了解JavaScript...
《Learning JavaScript Design Patterns》是Addy Osmani所著,本书在2016年5月2日保存,涵盖了JavaScript...这本书不仅是对设计模式的探讨,也是对JavaScript编程实践的深入解读,是专业开发者提升编程能力的宝贵资源。
接着,教程深入JavaScript的高级特性,如闭包(closures)、面向对象编程中的类(class)和继承(inheritance)、迭代器(iterable)和生成器(generator)、以及作用域(scope)。掌握这些概念对于深入理解...
JavaScript继承是面向对象编程(OOP)中的一个核心概念,它允许一个对象(称为子类或派生类)继承另一个对象(称为父类或基类)的属性和方法。JavaScript是一种基于原型的编程语言,它实现继承的方式与其他基于类的...
JavaScript是基于原型的面向对象语言,你需要了解构造函数、原型链、对象属性与方法、继承机制(原型链继承、借用构造函数、组合继承、寄生组合继承、原型式继承、ES6的类)。此外,还要掌握闭包和作用域,这是...
在JavaScript学习的领域里,继承的概念是一个非常核心的话题。本文将深入探讨如何利用JavaScript中的prototype(原型)来封装继承机制,以及如何实现面向对象的继承特性。 ### prototype与继承的关系 在JavaScript...
JavaScript中的继承是面向对象编程中的一个核心概念,它允许我们将一个类的属性和方法继承到另一个类上。...对于希望深入学习JavaScript继承机制的开发者来说,理解和掌握寄生组合式继承是一项不可或缺的技能。
JavaScript,也被称为JS,是一种广泛应用于网页和网络应用的脚本语言,主要在客户端运行,为用户提供动态交互体验。作为互联网技术的重要组成部分,JavaScript在现代Web开发中的地位不容忽视。"javascript权威指南与...