在谈Js之前,首先需要明确几个概念:
1.某一对象的原型仍是一个对象.
2.js原型继承的实质是复制,但也不是完全复制,而是子对象更改了什么数据,就复制什么数据.具体做法为创建一张成员维护表.如:
function Parent(b)
{
this.a = "a";
this.b = b==null ? "b" : b;
};
function Child(b)
{
Parent.call(this,b);
};
Child.prototype = new Parent();
var c = new Child();
alert(c.b)
3.当需要查找某个属性时,首先读对象实例自己维护的表.如果没有找到指定的成员,就要遍历整个原型链,直到原型为空的对象({}),或者到找到该成员为止。
4.每个函数都有一个prototype属性指向其原型对象,默认为{},即空对象.
5.每个对象都有一个constructor属性,默认指向本对象的构造函数(这句话没有讲完,请接看往下看)
6.Objcet对象的prototype属性是空对象{},空对象的constructor属性指向Object函数构造,所以所有对象的总原型都是Object(参见第4条)
7.对于new操作符,比如:
function Parent(b)
{
this.a = "a";
this.b = b==null ? "b" : b;
};
对于:
其实可以写成这样:
var p = {};
Person.call(p,"c");
这就很明白了,其实首先是创建了一个空对象,然后将这个对象以this参数传入构造函数Person,于是Person对象就new出来了.
好了,下面来说正题.上图:
其实这是别人画的一张图,画的很好,我就拿来主义了,呵呵.代码如下:
function MyObject()
{
this.constructor = arguments.callee; //正确维护constructor,以便回溯外部原型链
}
MyObject.prototype = new Object(); //人为构建外部原型链
function MyObjectEx()
{
this.constructor = arguments.callee; //正确维护constructor,以便回溯外部原型链
}
MyObjectEx.prototype = new MyObject(); //人为构建外部原型链
obj1 = new MyObjectEx();
obj2 = new MyObjectEx();
alert(obj1.constructor === MyObjectEx); //true
alert(MyObjectEx.prototype instanceof MyObject); //true
alert(MyObjectEx.prototype.constructor === MyObject); //true
alert(MyObject.prototype instanceof Object); //true
alert(MyObject.prototype.constructor === Object); //true
alert(obj1.constructor.prototype.constructor.prototype.constructor === Object); //true,完成了所有的回溯
学习JS的原型继承,最重要的就是搞清楚JS的原型链.
所谓原型链,就是一条记录了JS对象继承过程的链表,而其组成部分就是每个对象的constructor属性与函数的prototype属性.通过对象的constructor属性可以找到本对象的构造构数,通过构造构数prototype属性又可以找到其上一级的对象.就这样一级一级的回溯,直到Object.
还有一条隐藏的原型链,通过.proto属性维护,不过这是系统自行维护的,不需要人为参与,也不可见,虽然firefox浏览可以访问,但还是不推荐.
看似简单,但是陷阱很多,如下:
function Parent(){};
function Child(){};
Child.prototype = new Parent();
var p = new Parent();
var c = new Child();
alert(p.constructor == c.constructor) //true
p与c明明一个是基对象,一个是子对象,怎么会p.constructor == c.constructor呢?
当你alert(p.constructor),显示的是Person(),但当你alert(c.constructor)时,打印的还是Person(),这就奇怪了,c的constructor不是Child()吗?
原因就是第三行代码:
Child.prototype = new Parent();
文章开始时的第5条说过:每个对象都有一个constructor属性,默认指向本对象的构造函数,其实这句话没有说完:每个对象的prototype对象的constructor属性默认也指向本构造函数,但是,当你改变了其prototype所指对象后,情况就有点不同了,如上例,当指向Parent后,原型对象的constructor会指向Person,这是对的,然而,由于原型继承的本质是复制,会把这个属性值复制过来,会改变本对象的constructor属性,让其也指向Person.
但是,如果代码这样写,结果就不同了:
function Parent(){};
function Child(){};
var p = new Parent();
var c = new Child();
Child.prototype = new Parent();
alert(p.constructor == c.constructor) //false
我把它从第三行放到第五行.结果就是false了,原因是我先new对象,再更改原型.其实在对象被new出来之后,就与构造函数无关了,更改构造函数不会影响到已new出来的对象.
但是这样写的很少,因为这不符合面向对象的原则.回到刚才的话题,怎么才能在先设置原型再new对象的情况下让原型链记录正确呢?答案就是重新设置子对象的constructor属性:
function Parent(){};
function Child()
{
this.constructor = arguments.callee
};
Child.prototype = new Parent();
var p = new Parent();
var c = new Child();
通过这样的设置,就能达到那张图里所描绘的一条完整的原型链了.
参考的文章:
Javascript对象真经
悟透JavaScript
《悟透JavaScript》之 甘露模型(新)
分享到:
相关推荐
这份"javascript入门学习笔记"旨在为初学者提供一个全面且深入的JavaScript学习路径。 一、基础语法 JavaScript的基础包括变量、数据类型、操作符、流程控制等。变量用于存储数据,数据类型分为基本类型(如字符串...
这篇"JavaScript入门新手学习笔记"提供了全面的学习资源,适合初学者系统性地掌握这一技术。 笔记可能包含了以下关键知识点: 1. **基础语法**:JS的基础包括变量(var、let、const)、数据类型(如字符串、数字、...
总结一下,JavaScript面向对象编程主要包括类的表示(通过构造函数)、对象的创建(对象工厂、构造函数、原型模式)以及继承的实现(原型链)。理解这些概念对于深入学习JavaScript和开发复杂的JavaScript应用至关...
这篇学习笔记主要涵盖了JavaScript的基础语法和客户端JavaScript的相关知识。 1. **JavaScript基本语法**: - **变量声明**:未声明的变量尝试读取时会产生错误,而写入未声明的变量会创建一个全局变量。 - **...
原型和原型链是JavaScript继承的基础,理解这两个概念对于掌握面向对象编程至关重要。另外,ES6引入了类和模块,让JavaScript的面向对象编程更加简洁。 事件驱动编程是JavaScript的另一个关键特性,用于响应用户的...
本学习笔记将深入探讨JavaScript的核心概念,包括变量、数据类型、操作符、控制流程、函数、对象、数组、原型链、闭包等,并结合实际示例,如my.js、order.js、login.js等文件,来讲解其在实际项目中的应用。...
本学习笔记旨在帮助初学者快速掌握JavaScript的核心概念和技术,实现从入门到精通的过渡。 1. **基础语法** - 变量声明:JavaScript支持var、let和const关键字声明变量,理解它们的作用域和提升特性至关重要。 - ...
个人在学习前端JavaScript时的学习笔记,内含JavaScript的中基础知识点,以及案例。里面有兼容市面上浏览器的方法 1.知识点包括:基础语法,字符串操作,object对象,DOM对象,BOM对象,offset,client,scroll对象...
这篇学习笔记主要涉及了JavaScript的基础概念和一些高级特性,包括预编译、作用域、函数、对象原型、原型链、函数调用方式(如call、apply)、继承模式、对象克隆、数组操作、自定义类型判断以及错误处理机制。...
例如,JavaScript中的数组是一种特殊的对象,可以存储多个值,而构造函数和原型继承则是理解面向对象编程的关键。 关于压缩包内的"常用javascript函数.xls",这可能是一个包含常见JavaScript函数及其用途的清单,...
①了解js继承方法之前要了解js的原型和原型链,可以参考关于JavaScript原型的学习笔记 ②call和apply方法的运用 function Person(name,age) { this.name = name; this.age = age; } function Pp(name,age,sex) ...
这篇学习笔记将带你探索JavaScript的核心概念,包括变量、数据类型、控制流、函数、对象和类等,这些都是构建复杂应用程序的基础。 首先,我们要了解JavaScript的基础语法。在JavaScript中,变量是存储数据的容器,...
本学习笔记全面涵盖了JavaScript的语法和用法,旨在帮助初学者快速掌握并深入理解这门语言。 一、基础语法 JavaScript的基础包括变量、数据类型、操作符和流程控制。变量在JavaScript中使用`let`、`const`和`var`...
了解闭包和原型链是深入理解JavaScript的关键,它们对于函数的封装和对象的继承有着重要作用。 接着,要熟悉DOM操作,这是JavaScript与HTML交互的基础。通过DOM,我们可以创建、修改、删除网页元素,实现动态效果。...
在JavaScript中,由于没有传统的类,所以继承不是通过类来实现的,而是通过其他机制,如原型链继承和借用构造函数继承。 ### 一、原型链继承 原型链继承是JavaScript最基础的继承方式,它利用了原型对象的特性。每...
### JavaScript基础教程笔记知识点 #### 一、JavaScript简介 - **定义**:JavaScript是一种轻量级的编程语言,主要用于Web浏览器中的网页交互控制。 - **发展历史**:1995年由Netscape公司的Brendan Eich设计并...
根据提供的文件信息,可以看出这份“我的javascript学习笔记”主要涵盖了JavaScript中的几个关键概念和技术要点,包括正则表达式、AJAX以及一些JavaScript的核心语言特性。接下来将这些知识点进行详细的整理和解释。...
2. **对象与原型**:JavaScript的万物皆对象,理解原型链和原型继承是深入学习的关键。这包括构造函数、this关键字、Object.create()方法以及ES6中的class和继承。 3. **作用域与闭包**:理解作用域(全局和局部)...