一、原型prototype
1、定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
1 //构造函数满足大驼峰命名原则 2 function Person(name,age,sex){ 3 this.name = name; 4 this.age = age; 5 this.sex = sex; 6 this.height = 180; 7 this.weight = 150; 8 } 9 10 var person = new Person('james',18,'male'); 11 var person1 = new Person('marry',18,'female'); 12 //这是两个相似的函数但却独一无二的
2、利用原型特点和概念,可以提取共有属性。(这两个函数都要共有这属性,利用构造函数可以继承原型上的属性和方法,所以把这个属性写在了原型上)
1 //构造函数可以继承原型的属性和方法,可以提取共有属性 2 Person.prototype = { 3 height:180, 4 weight:150 5 } 6 //构造函数满足大驼峰命名原则 7 function Person(name,age,sex){ 8 this.name = name; 9 this.age = age; 10 this.sex = sex; 11 // this.height = height; 12 // this.weight = weight; 13 } 14 15 var person = new Person('james',18,'male'); 16 console.log(person) 17 var person1 = new Person('marry',18,'female'); 18 //这是两个相似的函数但却独一无二的
3、对象如何查看原型->隐式属性 _proto_ (这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。)
1 Person.prototype.name = 'abc'; 2 function Person(){ 3 //var this = { 4 // _proto_:Person.prototype 5 //} 6 7 } 8 9 //person.name = 'abc' 先去自身上找,如果自身没有,就沿着_proto_去原型上找。 10 11 var obj = { 12 name:'sunny' 13 } 14 15 var person = new Person(); 16 person._proto_ = obj 17 18 //person.name = 'sunny'
1 Person.prototype.name='abc' 2 function Person(){ 3 4 } 5 var person = new Person(); 6 //Person.prototype.name='sunny' 在原有的基础上把属性值给改了 7 //console.log(person.name)//sunny 8 //Person.prototype={ 9 //name:'sunny' 10 //} 把原型给改了换了一个新对象 11 //console.log(person.name)//abc 12 13 14 //var obj = {name:'a'} 15 //var obj1 = obj 16 //obj = {name:'b'} 17 //obj {name:'b'} 18 //obj1 {name:'a'} 19 20 21 //Person.prototype={ 22 //name:'sunny' 23 //} 把原型给改了换了一个新对象 24 //var person = new Person(); 25 //console.log(person.name)//sunny
4、对象如何查看对象的构造函数->constructor(可以手动更改)
1 //构造函数满足大驼峰命名原则 2 function Person(name,age,sex){ 3 this.name = name; 4 this.age = age; 5 this.sex = sex; 6 // this.height = height; 7 // this.weight = weight; 8 } 9 Car.prototype={ 10 constructor:Person 11 } 12 function Car(){ 13 14 } 15 16 var person = new Person('james',18,'male'); 17 var car = new Car(); 18 console.log(car.constructor)// function Person(){}
二、原型链
1、每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。
1 Grand.prototype.lastName = 'Fan'; 2 function Grand(){ 3 4 } 5 var grand = new Grand(); 6 Father.prototype = grand; 7 function Father(){ 8 this.name = 'xiaoming'; 9 } 10 var father = new Father(); 11 Son.prototype = father; 12 function Son(){ 13 this.hobbit = 'smoke'; 14 } 15 var son = new Son(); 16 console.log(son) 17 //son.hobbit 'smoke' 18 //son.name 'xiaoming' 19 //son.lastName 'Fan'
绝大多数对象的最终都会继承自Object.prototype var obj = Object.craete(null)//没有自己的原型,自己创建的系统不认
没有原型是没有原型上的所有方法的(undefined.toString(),null.toString())只有这两个是没有toString方法的
toString() 数字后面直接跟toString()会把那个点当成浮点型
方法的重写:原型上面有方法,自己又重新写了和一个同一个名字但是不同功能的方法,叫做方法的重写
1 //Object.prototype.toString = function(){} 2 3 Person.prototype = { 4 toString:function(){ 5 return 'fanfan'; 6 } 7 8 } 9 10 function Person(){ 11 12 13 } 14 15 var person = new Person()
//Object.prototype.toString()
//Number.prototype.toString()
//Array.prototype.toString()
//Boolean.prototype.toString()
//String.prototype.toString()
三、call/apply
作用:改变this的指向
区别:后面传的参数形式不同,call可以传多个参数,apply只能传两个参数,一个是作为函数上下文的对象,另一个是作为函数参数所组成的数组。
apply
apply()方法传入两个两个参数:一个是作为函数上下文的对象,另一个是作为函数参数所组成的数组。
1 var obj = { 2 name : 'linxin' 3 } 4 5 function func(firstName, lastName){ 6 console.log(firstName + ' ' + this.name + ' ' + lastName); 7 } 8 9 func.apply(obj, ['A', 'B']); // A linxin B
可以看到,obj是作为函数上下文的对象,函数func中的this指向了obj这个对象。参数A和B是放在数组中传入了func函数,分别对应func参数的列表元素。
call
call方法第一个参数也是作为函数上下文的对象,但是后面传入的是一个参数列表,而不是单个数组。
1 var obj = { 2 name: 'linxin' 3 } 4 5 function func(firstName, lastName) { 6 console.log(firstName + ' ' + this.name + ' ' + lastName); 7 } 8 9 func.call(obj, 'C', 'D'); // C linxin D
当使用 call 或者 apply 的时候,如果我们传入的第一个参数为 null,函数体内的 this 会指 向默认的宿主对象,在浏览器中则是 window。
1 var func = function( a, b, c ){ 2 console.log(this === window); // 输出:true 3 }; 4 func.apply( null, [ 1, 2, 3 ] );
但是如果是在严格模式下(use strict
),函数体内的 this 还是为 null。
用途
改变this的指向
1 var obj = { 2 name: 'linxin' 3 } 4 5 function func() { 6 console.log(this.name); 7 } 8 9 func.call(obj); // linxin
我们知道,call 方法的第一个参数是作为函数上下文的对象,这里把 obj 作为参数传给了 func,此时函数里的 this 便指向了 obj 对象。此处 func 函数里其实相当于
1 function func() { 2 console.log(obj.name); 3 }
借用别的对象的方法
1 var Person1 = function () { 2 this.name = 'linxin'; 3 } 4 var Person2 = function () { 5 this.getname = function () { 6 console.log(this.name); 7 } 8 Person1.call(this); 9 } 10 var person = new Person2(); 11 person.getname(); // linxin
从上面我们看到,Person2 实例化出来的对象 person 通过 getname 方法拿到了 Person1 中的 name。因为在 Person2 中,Person1.call(this) 的作用就是使用 Person1 对象代替 this 对象,那么 Person2 就有了 Person1 中的所有属性和方法了,相当于 Person2 继承了 Person1 的属性和方法。
调用函数
1 function func() { 2 console.log('linxin'); 3 } 4 func.call(); // linxin
apply、call 方法都会使函数立即执行,因此它们也可以用来调用函数。
1 function Wheel(wheelSize,style){ 2 this.wheelSize = wheelSize; 3 this.style = style; 4 5 } 6 function Sit(c,sitColor){ 7 this.c= c; 8 this.sitColor = sitColor; 9 } 10 function Model(height,width,len){ 11 this.height = height; 12 this.width = width; 13 this.len = len; 14 } 15 function Car(wheelSize,style,c,sitColor,height,width,len){ 16 Wheel.call(this,wheelSize,style); 17 Sit.call(this,c,sitColor); 18 Model.apply(this,[height,width,len]) 19 } 20 var car = new Car(100,'花里胡哨','猪皮','blue',1000,1900,4900); 21 console.log(car)