- [[prototype]] 原型
javaScript 中所有的对象都有一个内置属性[[prototype]], 是对其它对象的引用。那么它默认情况下引用的是什么对象呢
该属性指向的其构造函数的原型对象 [[prototype]]通过_proto_来访问 或者通过 Object.getPrototypeOf(obj) 来访问
<script type="text/javascript"> var obj={a:"apple"}; var num=new Number(10); var ifUp=true; console.log("obj.__proto__===Object.prototype:"+(obj.__proto__===Object.prototype)); console.log("num.__proto__===Number.prototype:"+(num.__proto__===Number.prototype)); console.log("ifUp.__proto__===Boolean.prototype:"+(ifUp.__proto__===Boolean.prototype)); console.log("obj.__proto__===Object.getPrototypeOf():"+(obj.__proto__===Object.getPrototypeOf(obj))); console.log("num.__proto__===Number.getPrototypeOf:"+(num.__proto__===Object.getPrototypeOf(num))); console.log("ifUp.__proto__===Boolean.getPrototypeOf:"+(ifUp.__proto__===Object.getPrototypeOf(ifUp)));
</script>
函数也是对象,那么函数也有内置的[[prototype]]属性: 那么函数的[[prototype]]指向什么呢'
<script type="text/javascript"> function foo() { } console.log("foo._proto_: "+(foo.__proto__==Function.prototype)); console.log("Object._proto_: "+(Object._proto_==Function.prototype)); console.log("Number.__proto__ === Function.prototype "+(Number.__proto__ === Function.prototype)); // true console.log("Boolean.__proto__ === Function.prototype "+( Boolean.__proto__ === Function.prototype));// true console.log("Object.__proto__ === Function.prototype "+(Object.__proto__ === Function.prototype)); // true console.log("String.__proto__ === Function.prototype "+(String.__proto__ === Function.prototyp)); // true console.log("Function.__proto__ === Function.prototype "+(Function.__proto__ === Function.prototype)); // true console.log("Array.__proto__ === Function.prototype "+(Array.__proto__ === Function.prototype)); // true console.log("RegExp.__proto__ === Function.prototype "+(RegExp.__proto__ === Function.prototype)); // true console.log("Error.__proto__ === Function.prototype "+(Error.__proto__ === Function.prototype)); // true console.log("Date.__proto__ === Function.prototype "+ (Date.__proto__ === Function.prototype)); </script>
执行结果如下:
可以看到所有构造器/函数的__proto__都指向Function.prototype,它是一个空函数(Empty function)
那么,那Function.prototype的__proto__是谁呢?
通过上面的截图我们可以看到 Function.prototype._proto_指向的是Object.prototype;
而:Object.prototype的_proto_指向null 既是 ojbect 位于[[prototype]]原型链的顶端。
- 原型链
由于_proto_是任何对象都有的属性,而js中万物皆对象,所有会形成一条_proto_连起来的链条,一直到头,就是Object.prototype._proto_指向null
<script type="text/javascript"> var A = function(){}; var a = new A(); console.log(a.__proto__); //A {}(即构造器function A 的原型对象) console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象) console.log(a.__proto__.__proto__.__proto__); //null </script>
当查找对象属性的时候,如果对象本身没有找到所需的属性,就会继续访问对象的[[prototype]]链所以JavaScript中所有的对象都可以调用Object的方法:比如:toString()
如果需要赋值的属性的是对象本事不存在,而在于原型链上会有三种情况产生
myObject.foo="bar"; //
1:如果原型链存在foo,并在该属性没有标记为只读的,那么会在myObject上添加一个foo属性,屏蔽原型链上的foo属性
2:如果原型链上存在foo,并在该属性被标记为只读的,这条语句会被忽略,不会发生屏蔽,如果运行在严格模式下会报错
3:如果原型链上存在foo并且标记为setter ,会直接的调用这个属性,不会再myObject上创建foo属性
使用Object.defineProperty(): 可以把属性强制性添加到myObject上,既是第一种情况屏蔽原型链上的属性
- _proto_ 和 prototype
很多同学都搞不清楚它们之之间有什么区别
_proto_:是所有对象(包括函数)都拥有的内置属性,读取的内置[[prototyope]]内置属性
prototype:是只有函数才有的