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

Posted manu-yyj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于原型的一些理解,尽量写的详细一点。相关的知识,希望对你有一定的参考价值。

学了前端一段时间了,对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");

    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__

今天写的很浅,还有很多问题都没有涉及,睡了还是写了很久。明天继续写原型这部分的,然后遇到的this,call这些也会写,慢慢来每天写点。

以上是关于关于原型的一些理解,尽量写的详细一点。的主要内容,如果未能解决你的问题,请参考以下文章

关于Django中间件自己的一点理解

关于JS原型以及原型链instanceof的一些理解

关于js的原型链,__proto__,prototype的理解

自己写的一个HTML的小网页

我想学CC2530,请问对C语言基础有啥要求?尽量详细一些

灰度图像直方图变换的一些代码