关于原型的一些理解,尽量写的详细一点。
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这些也会写,慢慢来每天写点。
以上是关于关于原型的一些理解,尽量写的详细一点。的主要内容,如果未能解决你的问题,请参考以下文章