关于原型的一些理解,尽量写的详细一点。

 学了前端一段时间了,对js当时花了很多时间但是随着后面学习框架有些就忘了。现在从新开始记录下重要的知识点。有很多知识也是查阅js高程和别人的博客,所用的一些例子也是引用那些觉得很有代表意义的,在文章最后贴出有关的博客。有错的地方也请大家指出。有些知识深究的话我能力有限,也不知道;所以很多作为一个结论记住就行。

1.首先什么是对象,什么是函数对象。有些地方也叫函数,我查了下函数和函数对象应该是指代的同一个东西,没有区别。首先

 var a={"name":"hello"}; 这是一个普通的对象。 function f1(){};    var f2 = function(){}; 这是函数对象。那么函数对象和对象又有什么不同了。函数有个叫原型的东西是个对象,但是对象没有。这里引入了 prototype 这个属性,那么这个就是原型对象了,当然不是。它是个指针指向原型对象。这里要记住prototype是个指针后面虽然还有继承有关但是先记住是个指针。这里就先说到这里,区别函数对象和对象,以及一个重要属性prototype,对象没这个属性。

2,那么对象和函数对象又有什么联系了,首先创建一个普通的对象var person = {}或者var 0=new object()。这是个普通的对象,通过这种字面量可以创造很多单个对象。但是会产生大量重复代码,所以有了工厂模式的出现。

function creatPerson (name, age) {
    var person = new Object(); 
    person.name = name;
    person.age = age;
    person.sayName = function () {
        alert(this.name);
    };
    return person; 
}

var person1= creatPerson ("tom",29)
 

他能创建一个包含一些信息的person对象,可以多次调用这个函数。但是却没有解决对象的识别问题(不知道这个对象的类型)。所以之后重头戏来了,有了构造函数,这个知识点就涉及原型了。

function CreatePerson(name, age, say){
    this.name = name;
    this.age = age;
    this.say = say;
    this.should = function(){
        console(this.say);
    }
}
var person1 = new CreatePerson("","","");

这个函数也很简单,但是和之前的工厂模式有了些区别。这个函数有个很重要的 new 操作符。看一个实例:

function Animal(name){
           this.name = name;
         }
    Animal.color = "black";
    Animal.prototype.say = function(){
            console.log("I'm " + this.name);
         };
    var cat = new Animal("cat");

    console.log(
            cat.color, //undefine
            cat.name  //cat
 );
    cat.say(); //I'm cat

     console.log(
            Animal.name, //Animal
            Animal.color //back
   );
    Animal.say(); //Animal.say is not a function

这个函数没看答案之前有可能你是不太清楚,但是看了答案你是应该是能得出一些结论的。虽然你可能不知道发生了什么。首先  console.log( Animal.name, //Animal Animal.color //back ); 这个比较简单没什么说的,不懂的函数的name属性可以看下。 cat.color, //undefine 这个是重点,这里看的出来构造出来的实例并没有继承到color这个属性,那么就要引入构造函数的工作的模式了。关键的new字符,js高程是这么解释的:

1'创建一个新的对象;

2'将构造函数作用域赋给新的对象(即this指向新对象);

3'执行构造函数里面的代码;

4'返回新的对象。 

new Animal("cat") = {

    var obj = {};

    obj.__proto__ = Animal.prototype;

    var result = Animal.call(obj,"cat");
//var result = obj.Animal("cat")。相当于Animal在obj作用域里面运行
return typeof result === 'object'? result : obj; }

这是一个模仿new运行机制的伪代码,这里我们看到一个新的东西出现了 __proto__  ,先给这个过程看完:obj的__proto__ 指向Animal的原型对象prototype然后你大概懂了

  cat.say(); //I'm cat 之后,在obj对象的执行环境调用Animal函数并传递参数“cat”。 相当于var result = obj.Animal("cat")。 当这句执行完之后,obj便产生了属性name并赋值为"cat"。可能第二个你看的不太明白那你就可以看看call属性,以及this了。这里先不提,后面可以在仔细做下笔记。引入了__proto__ 那么就相当于引入了原型链了,当你实例化一个对象,就会形成一个原型链,他会去找构造函数的prototype,然后逐级向上寻找,其实原型的重点是__proto__ ,我这里将引入一两道例题帮助自己记忆,以及自己的理解。

  var animal = function(){};
    var dog = function(){};
    animal.price = 2000;
    dog.prototype = animal;
    var tidy = new dog();  //tidy.constructor=dog;实例tidy可以通过授权找到它并用以检测自己的构造函数
    console.log(dog.price);   //undefined
    console.log(tidy.price);   // 2000

1'首先 dog.prototype = animal;这里没有问题的, 我们可以赋值任何类型的对象到原型上,但是不能赋值原子类型的值, 比如如下代码是无效的: Foo.prototype = 1;

2'将 animal的值赋给dog的原型对象。 console.log(dog.price);针对这句代码。首先是dog自己的本身的函数是没price这个属性的,然后原型上有,但是两者是没有关系的。

3’ 它先通过查找自生,然后再循着__proto__去原型链中寻找,全局中也没有,都没有所以读取不到price这个属性。

    var Animal = function(){};   Animal.prototype.say = function(){ alert("a"); };     Animal.say()   //Animal.say s not a function            

这个简短的例子也是能说明问题的,然后在来看下面这个例子:

  var animal = function(){};
    var dog = function(){};

    animal.price = 2000;
    dog.__proto__ = animal;
    var tidy = new dog();

    console.log(dog.price) //2000
    console.log(tidy.price) // undefined
1. dog.__proto__ = animal;直接找到 animal,获取值dog.price==2000;
2. tidy.__proto__= dog.prototype;
3.
tidy.__proto__.__proto__ === dog.prototype.__proto__=== Object.prototype;通过这个原型链确实找不到。这里要区别prototype和__proto__

....................................................................................................................................................................................................................................................................

现在还有个constructor。,constructor始终指向创建当前对象的构造函数。

function Person(name,age){
  this.name = name;
  this.age = age;
}
 
Person.prototype = {
  getName:function(){
    return this.name;
  },
  getAge:function(){
    return this.age;
  }
}
 
var p = new Person("Nicholas",18);
console.log(p.constructor); //Object()

这里p.constructor不等于person是因为上面的给她相当于从new成一个新的对象

Person.prototype = new Object({
  getName:function(){
    return this.name;
  },
所以结果是boject。然后现在对new constructor prototype __proto__有了认识之后来说说原型链。首先是构造函数的原型链。

  构造函数也是有 __proto__属性的,然后也会形成一个原型链。

Constructor ----> Function.prototype ----> Object.prototype ----> null  

 

1,Constructor 的 __proto__ 是 Function.prototype
2,Function.prototype 的 __proto__ 是 Object.prototype
3,Object.prototype 的 __proto__ 是 nullda
答:这个了也只能这么理解,一个函数由于是Function类型,所以它的__proto__是Function.prototype,而Function本身也是个函数(可以new Function嘛),所以Function的__proto__也是Function.prototype。然而然后Function.prototype自然是一个对象,所以Function.prototype的__proto__是Object.prototype。最后指向js的万恶之源null。为什么说是万恶之源了,因为才学js就听说万物皆继承于null。
 
然后构造函数的实例又是怎么形成的原型链了,

function f()={};

var obj=new f();

这是一个普通实例的原型的原型链。

 

 还有很多没搞懂的,这部分内容确实多先到这吧,以后在慢慢更新。

原文地址:https://www.cnblogs.com/manu-yyj/p/9102991.html