js——prototype、__proto__、constructor

                                    Object                                   

1. Object是一个函数(typeof Object;//function)。Object构造器创建了一个对象包装器

1 //Object{}
2 var o = new Object(null);
3 //Object{}
4 var o = new Object(defined);
5 //Number
6 var o = new Object(1);
7 //Boolean
8 var o = new Object(true);
View Code

2. Object.prototype属性是Object的原型对象

3. js中几乎所有objects都是Object的实例,一个object会继承Object.prototype的所有属性,这些属性也可能被屏蔽。

4. JavaScript没有子类对象,原型用于为某些表现为对象的函数创建一个“基类”对象 

                                   Constructor                                   

Foo函数在声明时,Foo.prototype有一个默认属性.constructor,这个属性默认指向Foo

它不表示“由。。。构造”!

var a = new Foo();
a.constructor === Foo;//true
//a.__proto__ == Foo.prototype
//a.constructor被委托给Foo.prototype
//Foo.prototype.constructor默认为Foo

对象的constructor默认指向一个函数,这个函数可以通过对象的.prototype引用

                                    __proto__                                   

1. __proto__属性是个可访问的属性,它可以用来访问[[Prototype]]

2. __proto__的使用不被鼓励。它一开始并没有被包含在EcmaScript中,但是浏览器却一定要实现它。为了保证兼容性,未来将会在ECMAScript2015中规范并支持。

更推荐使用Object.getPrototypeOf/setPrototypeOf

3.__proto__ 的实现,get和set:

1 Object.defineProperty(Object.prototype, "__proto__", {
2     get: function(){
3         return Object.getPrototyperOf(this);
4     },
5     set: function(o){
6         Object.setPrototypeOf(this, o);
7         return o;
8     }
9 });
View Code

                                    prototype                                   

1. 函数中有prototype对象,非函数没有prototype对象

2. 函数的prototype在new的时候起作用。让new func()出来的对象的__proto__指向func.prototype

3. 那没有自己设置prototype的函数的prototype是什么值?

function a(){}
//a.__proto__ -->function(){[native code]}
//a.constructor -->function Function{[native code]}
//a.prototype.__proto__ -->Object.prototype
//a.prototype.constructor --> a

                                    继承和原型链                                   

1. 继承:js只有一个构造器objects。每个object有一个私有属性[[Prototype]],它指向另一个对象,称为它的prototype对象。

2. prototype对象也有它的prototype对象,最后达到null。null没有prototype对象,因此它是原型链的最后节点

3. 原型链:当想要访问一个对象属性时,它从当前对象开始一直沿着它的原型向上访问,直到null

4. 基于原型链的继承

  • 继承属性 
myObject.foo = "bar";

        myObject有foo属性,修改foo的值(屏蔽原型链上的) 

myObject无foo属性,沿myObject原型链向上查找,且原型链上有foo属性

    • 可写:在myObject添加foo属性(屏蔽原型链上的)
    • 不可写:语句被忽略/报错(严格模式)
    • 是setter:不改变 
  • 继承方法

        与继承属性类似

5. 创建对象的不同方法及原型链

 1 //1. 普通语法
 2 //o --> Object.prototype
 3 var o = {a:1};
 4 //o --> Array.prototype -->Object.prototype 
 5 var o = [1, 2]; 
 6 //f --> Function.prototype -->Object.prototype
 7 function f(){
 8     return 2;
 9 }
10 
11 //2. new
12 function Graph(){
13     this.vertices = [];
14     this.edges = [];
15 }
16 Graph.prototype = {
17     addVertex: function(v){
18         this.vertices.push(v);
19     }
20 };
21 //g-->Graph.prototype--> Object.prototype
22 var g = new Graph();
23 
24 //3. Object.create
25 //a-->Object.prototype
26 var a = {a:1};
27 //b-->a-->Object.prototype
28 var b = Object.create(a);
29 
30 //4. class关键字
View Code

 6. 性能

  • 在原型链上查找属性比较耗时,试图访问不存在的属性时会遍历整个原型链
  • 遍历对象的属性时,原型链上的每个可枚举属性都会被枚举出来
  • hasOwnProperty是js中唯一一个只涉及对象自身属性而不会遍历原型链的方法
  • 仅判断值是否为undefined不足以检测一个属性是否存在,它可能存在而值恰好为undefined
var a = {
    b: undefined
};
a.b;//undefined

7. 不好的实践:扩展原生对象的原型 

         prototype和getPrototypeOf(__proto__)         

在函数中有一个属性prototype,它是和new操作符相关的特殊属性

在内存中创建一个对象,在运行函数前,会把[[prototype]]链接到函数的prototype

var o = new Foo();

 等价于:

var o = new Object();
o.[[prototype]] = Foo.prototype;
Foo.call(o);
//返回o

总的来说:

prototype is for types, while Object.getPrototypeOf() is the same for instance

在prototype中定义的属性可以被new出来的对象共享

        我的总结吧~         

1. __proto__是每个对象都有的属性,用于访问对象的原型,形成原型链路

2. prototype是函数才有的属性,它在new的时候起作用。

    var a = new A();//使得a.__proto__ = A.prototype

3. 为什么要在函数中加一个prototyp属性?(个人理解)

   如果不加的话,只能有两种情况:a.__proto__ = A 或者a.__proto__ = A.__proto__

   A是一个函数,而a希望是一个对象,这样会使得一个对象有函数的属性,这就不太合理了吧。 

4. 与C++类的简单比较

C++ js
class A(){
  public:
      A(){}
}
function A(){
}
A.prototype={
}
  • C++:定义一个类A,A中包括了一个构造函数A(),并封封装了需要的属性
  • js:定义一个function A(){},A有prototype属性,A.prototype中定义需要的属性
  • 所以,这两个的构造函数和封装属性的对象有点反过来的意思吧 

5. constructor

function A(){}//定义一个函数
A.prototype.constructor == A;//true

下面图的关联关系是从chrome运行结果整理出来的

参考:

1. 《你不知道的javascript》上卷

2. MDN:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

最后,

不企图只看一篇文章然后懂得所有,还是要多翻几篇文章吧。

原文地址:https://www.cnblogs.com/coolqiyu/p/7128748.html