这里有新鲜出炉的 Javascript 教程,程序狗速度看过来!
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
这篇文章主要针对 javascript 中的原型、原型链深入理解,原型是 JavaScript 中一个比较难理解的概念,本文为大家解决这个难题,感兴趣的小伙伴们可以参考一下
原型是 JavaScript 中一个比较难理解的概念,原型相关的属性也比较多,对象有 "prototype" 属性,函数对象有 "prototype" 属性,原型对象有 "constructor" 属性。
一、初识原型在 JavaScript 中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript 的对象中都包含了一个 "[[Prototype]]" 内部属性,这个属性所对应的就是该对象的原型。 "[[Prototype]]" 作为对象的内部属性,是不能被直接访问的。所以为了方便查看一个对象的原型,Firefox 和 Chrome 中提供了__proto__这个非标准(不是所有浏览器都支持)的访问器(ECMA 引入了标准对象原型访问器 "Object.getPrototype(object)")。在 JavaScript 的原型对象中,还包含一个 "constructor" 属性,这个属性对应创建所有指向该原型的实例的构造函数
二、规则 在 JavaScript 中,每个函数 都有一个 prototype 属性,当一个函数被用作构造函数来创建实例时,这个函数的 prototype 属性值会被作为原型赋值给所有对象实例(也就是设置 实例的 `__proto__` 属性),也就是说,所有实例的原型引用的是函数的 prototype 属性。(****` 只有函数对象才会有这个属性!`****)
new 的过程分为三步
- var p = new Person('张三',20);
1. var p={}; 初始化一个对象 p。 2. p._proto_=Person.prototype;,将对象 p 的 __proto__ 属性设置为 Person.prototype 3. Person.call(p," 张三 ",20); 调用构造函数 Person 来初始化 p。关于 call/apply 使用
三、初识 Object Object 对象本身是一个函数对象。(CODE TEST) 既然是 Object 函数,就肯定会有 prototype 属性,所以可以看到 "Object.prototype" 的值就是 "Object {}" 这个原型对象。反过来,当访问 "Object.prototype" 对象的 "constructor" 这个属性的时候,就得到了 Obejct 函数。 另外,当通过 "Object.prototype._proto_" 获取 Object 原型的原型的时候,将会得到 "null",也就是说 "Object {}" 原型对象就是原型链的终点了。 四、初识 Function 如上面例子中的构造函数,JavaScript 中函数也是对象,所以就可以通过_proto_查找到构造函数对象的原型。 Function 对象作为一个函数,就会有 prototype 属性,该属性将对应 "function () {}" 对象。 Function 对象作为一个对象,就有__proto__属性,该属性对应 "Function.prototype",也就是说,"Function._proto_ === Function.prototype"。
在这里对 "prototype" 和 "proto" 进行简单的介绍: 对于所有的对象,都有__proto__属性,这个属性对应该对象的原型. 对于函数对象,除了__proto__属性之外,还有 prototype 属性,当一个函数被用作构造函数来创建实例时,该函数的 prototype 属性值将被作为原型赋值给所有对象实例(也就是设置实例的__proto__属性)
原型链结构图
原型链因为每个对象和原型都有原型,对象的原型指向原型对象, 而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。
一、属性查找 当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶部(也就是 Object.prototype),如果仍然没有找到指定的属性,就会返回 undefined。
- function Person(name, age){
- this.name = name;
- this.age = age;
- }
- Person.prototype.MaxNumber = 9999;
- Person.__proto__.MinNumber = -9999;
- var will = new Person("Will", 28);
- console.log(will.MaxNumber); // 9999
- console.log(will.MinNumber); // undefined
在这个例子中分别给 "Person.prototype" 和 "Person.proto" 这两个原型对象添加了 "MaxNumber" 和 "MinNumber" 属性,这里就需要弄清 "prototype" 和 "proto" 的区别了。
"Person.prototype" 对应的就是 Person 构造出来所有实例的原型,也就是说 "Person.prototype" 属于这些实例原型链的一部分,所以当这些实例进行属性查找时候,就会引用到 "Person.prototype" 中的属性。
对象创建方式影响原型链
- var July = {
- name: "张三",
- age: 28,
- getInfo: function(){
- console.log(this.name + " is " + this.age + " years old");
- }
- }
- console.log(July.getInfo());
当使用这种方式创建一个对象的时候,原型链就变成下图了. July 对象的原型是 "Object.prototype" 也就是说对象的构建方式会影响原型链的形式。
{} 对象原型链结构图
综图所述 1. 所有的对象都有__proto__属性,该属性对应该对象的原型. 2. 所有的函数对象都有 prototype 属性,该属性的值会被赋值给该函数创建的对 3. 象的_proto_属性. 4. 所有的原型对象都有 constructor 属性,该属性对应创建所有指向该原型的实例的构造函数. 5. 函数对象和原型对象通过 prototype 和 constructor 属性进行相互关联.
来源: http://www.phperz.com/article/17/0626/266933.html