深刻理解下js的prototype
参考 http://aralejs.org/class/docs/competitors.html, http://www.iteye.com/topic/248933,http://www.cnblogs.com/qiantuwuliang/archive/2011/01/08/1930548.html
1、使用Dog.prototype.__proto__
function Animal() {}
function Dog() {} // 要让 Dog 继承 Animal, 只需:
Dog.prototype.__proto__ == Animal.prototype; // 实例化后
var dog = new Dog();
// dog.__proto__ 指向 Dog.prototype
// dog.__proto__.__proto__ 指向 Animal.prototype
// 原型链已成功建立起来,而且很清晰
function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
}
// 要让 Dog 继承 Animal, 只需:__ 2个_
Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
//Dog.prototype = new Animal ; //Animal的构造函数和自己的prototype也都放到Dog上
Dog.prototype.haha = function () {};//
Dog.prototype.haha.tata = 4;
var dog = new Dog("sdd","bbb");
var animal = new Animal("aaaa");
console.log(dog);
console.log(Dog.prototype);
console.log(animal.__proto__); console.log("11 "+(dog instanceof Animal));
console.log("11 "+(animal instanceof Dog));
Dog {name: "sdd", talk: function, run: function} name: "sdd"
__proto__: Dog constructor: function Dog(name) { arguments: null
caller: null
length: 1
name: "Dog"
prototype: Dog
__proto__: function Empty() {}
<function scope> __proto__: Object run: function () {}
talk: function () {}
__proto__: Object
__proto__指向了dog本身,并且有constructor,开始循环引用了。dog.__proto__=Dog.prototype。
dog本身的Dog.prototype没有被覆盖,一个标准的prototype,包括constructor和__proto__,我们只覆盖了这个标准的prototype的__proto__而已。
如果不加__proto__
function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(name) {
Animal.call(this,name)
}
// 要让 Dog 继承 Animal, 只需:
Dog.prototype = Animal.prototype; // 实例化后
var dog = new Dog("sdd");
console.log(dog);
返回
- name: "sdd"
- __proto__: Object
- run: function () {}
- talk: function () {}
- __proto__: Object
第二种原型链没有建立,没有constructor,只是简单的把方法赋值过来了。上面用 console.log(dog instanceof Animal ) 都返回ture。
function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(name) {
Animal.call(this,name)
}
// 要让 Dog 继承 Animal, 只需:
Dog.prototype = Animal.prototype;//有没有有__proto__都会被覆盖
Dog.prototype = {
qqq: function() {},
wwww: function() {}
} // 实例化后
var dog = new Dog("sdd");
console.log(dog);
console.log(dog instanceof Animal );
Dog {name: "sdd", qqq: function, wwww: function}
name: "sdd"
__proto__: Object
qqq: function () {}
wwww: function () {}
__proto__: Object
Dog.prototype被覆盖了,本身的constructor和__proto__不存在了,变 Animal.prototype了。
2,使用new
function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
}
// 要让 Dog 继承 Animal, 只需:__ 2个_
//Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
Dog.prototype = new Animal ; //Animal的构造函数和自己的prototype也都放到Dog上
Dog.prototype.haha = function () {};
var dog = new Dog("sdd","bbb");
var animal = new Animal("aaaa");
console.log(dog);
console.log(dog.__proto__);
console.log(animal.__proto__);
console.log(dog.__proto__===Dog.prototype);
Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}
age: "sdd"
__proto__: Animal
haha: function () {}
name: undefined
__proto__: Object
run: function () {}
talk: function () {}
__proto__: Object
new 是调用构造函数的,会把构造函数上的属性拿过来,没有constructor,只有new 带构造函数。__proto__是实例化后才有,他代表的原型链,可以共享的原型链,上图中方法haha 也放到__proto__中了。
Dog.prototype被覆盖了,本身的constructor和__proto__不存在了,变 new Animal了,于是构造函数都传过来了。
没有继承的情况下,如下图所示,prototype没有被覆盖,constructor保留,是Dog本身这个函数。dog.constructor === Dog.prototype.constructor
function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
} var dog = new Dog("sdd","bbb"); console.log(dog); //结果 Dog {age: "sdd", getName: function}
age: "sdd"
getName: function (){}
__proto__: Dog
constructor: function Dog(age,name) {
__proto__: Object
constructor: function Dog(age,name) {
arguments: null
caller: null
length: 2
name: "Dog"
prototype: Dog
__proto__: function Empty() {}
<function scope>
按照《悟透javascript》书中说的,new形式创建对象的过程实际上可以分为三步:
第一步是建立一个新对象(叫A吧);
第二步将该对象(A)内置的原型对象设置为构造函数(就是Person)prototype 属性引用的那个原型对象;
第三步就是将该对象(A)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。
其中第二步中出现了一个新名词就是内置的原型对象,注意这个新名词跟prototype对象不是一回事,为了区别我叫它inobj,inobj就指向了函数Person的prototype对象。在person的prototype对象中出现的任何属性或者函数都可以在one对象中直接使用,这个就是javascript中的原型继承了。
总结: 1)Dog.prototype = Animal.prototype 或者Dog.prototype.__proto__ = Animal.prototype 时,dog instanceof Animal 都是true。Dog.prototype.__proto__ = Animal.prototype,实际实例化后是 dog.__proto__.__proto__=Animal.prototype。沿着A的原型链查找 如果有一个原型和B.prototype相等 则返回true , 如:A.__proto__.__proto__ === B.prototype 则返回true
js的 instanceof 是根据什么来判断两个对象的继承关系?参考:http://yxc-gdut.iteye.com/blog/1812766
js的instanceof是根据prototype来判断两个对象是否存在继承关系,A instanceof B, js会沿着A的原型链查找 直到找到A.__proto__ === B.prototype 返回true。
一句话__proto__一层层都是指向继承的,最终到基本类型上。没有继承的就是他的protoype,包含constructor: function () {},__proto__: Object,和他自己加的方法。
下图展示的new方法的,Dog.prototype = new Animal ;所以dog第一层__proto__有name, new把构造函数有传入了。只有有prototype chrome下才能展示出来下面的结构。
Dog {age: "sdd", name: undefined, haha: function, talk: function, run: function}
age: "sdd"
__proto__: Animal
haha: function () {}
name: undefined
__proto__: Object
run: function () {}
talk: function () {}
__proto__: Object
2)理解下function ,如下图。function ,包括 arguments, caller,length,name ,prototype,__proto__,他的prototype,又分为constructor: function () {},__proto__: Object,然后constructor这个function 又继续循环。
__proto__他从别的原型链继承过来可以直接用的,prototype是他要加在自己原型链上的,供别人调用,或者直接实例化后,别人可以直接调用转成__proto__的。
run: function () {}
arguments: null
caller: null
length: 0
name: ""
prototype: Object
constructor: function () {}
__proto__: Object
__proto__: function Empty() {}
var AAA= function(name) {
this.name=222;
}
AAA.dhj="123";
AAA.prototype.www=function(){};
var aaa=new AAA();
console.log(aaa);
有继承关系的__proto__他指向的是指定的继承的那个,没有继承关系的__proto__依然保留constructor: function () {},__proto__: Object。
AAA {name: 222, www: function}
name: 222
__proto__: Object
constructor: function (name) {
www: function (){}
__proto__: Object
按照javascript的说法,function定义的这个是一个Object(对象),而且还是一个很特殊的对象,这个使用function定义的对象与使用new操作符生成的对象之间有一个重要的区别。这个区别就是function定义的对象有一个prototype属性,使用new生成的对象就没有这个prototype属性。prototype属性又指向了一个prototype对象,注意prototype属性与prototype对象是两个不同的东西,要注意区别。在prototype对象中又有一个constructor属性,这个constructor属性同样指向一个constructor对象,而这个constructor对象恰恰就是这个function函数本身。
下面分析下constructor
function Animal(name) {
this.name = name;
var a=1;
}
Animal.prototype.talk=function(){};
var animal = new Animal("aaaa");
function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
}
// 要让 Dog 继承 Animal, 只需:__ 2个_
//Dog.prototype.__proto__ = Animal.prototype ; // 实例化后
Dog.prototype = animal ; //注意这里啊,
Dog.prototype.constructor = Dog;//animal本身也有constructor,animal本身也指定到这里。引用传递。animal已经实例化了
var dog = new Dog("sdd","bbb"); console.log(dog); console.log(dog.constructor);; console.log(animal); console.log(animal.constructor);
Dog {age: "sdd", getName: function, name: "aaaa", constructor: function, talk: function}
age: "sdd"
getName: function (){}
__proto__: Animal function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
} Animal {name: "aaaa", constructor: function, talk: function}
constructor: function Dog(age,name) {
name: "aaaa"
__proto__: Animal function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
this.getName = function (){};
}
深刻理解下js的prototype的更多相关文章
- 再深刻理解下web3.js中estimateGas如何计算智能合约消耗的gas量
我们可使用web3.js框架的estimateGas函数获得一个以太坊智能合约的Gas估计值 ,通过执行一个消息调用或交易,该消息调用或交易直接在节点的VM中执行,并未在区块链中确认,函数会返回估算使 ...
- 简单理解js的prototype属性
在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的pr ...
- 深入理解js的prototype以及prototype的一些应用
上一篇讲了js的prototype概念,在这里回顾一下prototype的定义: prototype是函数的一个属性,并且是函数的原型对象.引用它的必然是函数,这个应该记住. 但是,很奇怪,各位看官, ...
- js Array.prototype.join.call(arguments,",") 理解
prototype 属性使您有能力向对象添加属性和方法. join() 方法:把数组的所有元素放入一个字符串.元素通过指定的分隔符进行分隔. call() 方法可以用来代替另一个对象调用一个方法. A ...
- 关于JS的prototype
在接触JS的过程中,随着理解的深入会逐渐的理解一些比较深奥的理论或者知识,那么今天我们来介绍一下比较难理解的prototype和constructor. 初步理解: 在说prototype和const ...
- JS的prototype
初步理解: 在说prototype和constructor之前我们先得看几个例子. 1 2 3 4 function name(obj){ alert(obj)//"uw3c&quo ...
- [译] 所有你需要知道的关于完全理解 Node.js 事件循环及其度量
原文地址:All you need to know to really understand the Node.js Event Loop and its Metrics 原文作者:Daniel Kh ...
- Nodejs第一天-{Nodejs基础 深刻理解浏览器 环境变量 基础语法}
Nodejs第一天 1.什么是Nodejs Nodejs是一个可以运行(解析)ECMAScript的环境; ECMAScript是规定了一些列的语法 ,这些语法想要解析的执行就需要放在某个环境 ...
- 方便大家学习的Node.js教程(一):理解Node.js
理解Node.js 为了理解Node.js是如何工作的,首先你需要理解一些使得Javascript适用于服务器端开发的关键特性.Javascript是一门简单而又灵活的语言,这种灵活性让它能够经受住时 ...
随机推荐
- AtCoder Regular Contest 081 F - Flip and Rectangles
题目传送门:https://arc081.contest.atcoder.jp/tasks/arc081_d 题目大意: 给定一个\(n×m\)的棋盘,棋盘上有一些黑点和白点,每次你可以选择一行或一列 ...
- Codeforces Round #542(Div. 2) D1.Toy Train
链接:https://codeforces.com/contest/1130/problem/D1 题意: 给n个车站练成圈,给m个糖果,在车站上,要被运往某个位置,每到一个车站只能装一个糖果. 求从 ...
- C3 Transitions, Transforms 以及 Animation总结
C3 Transitions, Transforms 以及 Animation总结 前言 昨天有人咨询我面试的注意事项, 突然就意识到自己这块非常差, 竟然没有任何的印象, 准备看着大神老师的博客, ...
- Excel 宏练习
任务描述: 利用 Excel 绘制函数图像 f(x)=x^2/3+0.9*(3.3-x^2)^1/2*sin(a*x),并通过按钮事件来刷新图像. 问题分析: 可以参考类似 Matlab 绘图的方式, ...
- python关于文件的一些记录
1.文件打开: file("data.txt")或open("data.txt")注意不要漏了文件的后缀.(不加参数时,file为你默认为'r',reading ...
- Nginx重写规则
Nginx的重写规则,依赖于pcre库(perl compatible regular expression).所以在安装的时候一定要让nginx支持这个功能,以及安装pcre-devel,prce. ...
- php 使用serialize() 和 unserialize() 让对象成超级变量
手册里面的原话和一些总结: php函数serialize()与unserialize()说明及案例.想要将已序列化的字符串变回 PHP 的值,可使用unserialize().serialize()可 ...
- java.lang.NoSuchMethodError: javax.persistence.OneToMany.orphanRemoval()
原因:hibernate-jpa-2.0-api-1.0.0.Final.jar.ejb3-persistence.jar中的javax.persistence与javaEE 5 Librares中的 ...
- qt QTableView/QTableWidget样式设置
转载请注明出处:http://www.cnblogs.com/dachen408/p/7591409.html 选中设置: QTableView::item:selected { background ...
- python基础一 day2 数据类型
int: bool: 类型转换: str到int有条件,str必须是数字, "123e"是错误的 bool转换为int类型,需要int(x) 结果: 结果: 空字 ...