javascript对象使用总结
一、总结
一句话总结:js对象的主要知识点是创建对象和继承,并且创建对象和继承的方法都是逐步层层递进的
创建对象 继承 原型
创建对象
1 <script> 2 function Monster(){} 3 Monster.prototype={ 4 constructor: Monster, 5 name:'喽啰', 6 job:['巡山','打更'], 7 run:function() {return this.name+'的工作是'+this.job } 8 } 9 //构造函数和原型组合模式 10 function Monster(name,arr){ 11 constructor: Monster, 12 this.name=name 13 this.job=arr 14 } 15 Monster.prototype={ 16 run:function() {return this.name+'的工作是'+this.job } 17 } 18 var monsterI=new Monster('小旋风',['巡山','打更','砍柴']) 19 var monsterII=new Monster('小钻风',['巡山','打更','挑水']) 20 alert(monsterI.run()) 21 alert(monsterII.run()) 22 </script>
继承
1、js中的原型的意义是什么?
共享
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。可以把那些不变的属性和方法,直接定义在prototype对象上。
2、对象的apply和call方法的主要用途是什么?
对象冒充
对象的apply和call方法实现对象冒充
1 <script> 2 //构造函数模式 3 //注意:构造函数不需要使用 return语句返回对象,它的返回是自动完成的 4 function People(name,weapon){ 5 this.name=name; 6 this.weapon=weapon; 7 this.run=function(){ 8 return this.name+'的武器是'+this.weapon 9 } 10 } 11 var wujing=new People('沙悟净','禅杖'); 12 var wukong=new People('孙悟空','金箍棒'); 13 var bajian=new People('猪八戒','钉耙'); 14 //alert(wujing.run()) 15 //alert(wujing instanceof People) 16 var monster=new Object(); 17 //People.call(monster,'妖怪','葫芦') 18 People.apply(monster,['妖怪','葫芦']) 19 // alert(monster.run()) 20 // alert(monster.name) 21 var monster1=new People('小妖','长矛') 22 var monster2=new People('小妖','长矛') 23 alert(monster1.run()+'\n'+monster2.run()) 24 alert(monster1.run==monster2.run)//两个对象实例的地址是不同的,说明两个对象会占用两个地址空间的内存 25 26 </script>
多继承实例
<script> function Monkey(_type,_home){ this.type=_type; this.home=_home; this.say= function() { alert('我是快乐的小猴子,家住'+this.home) }; } function Hero(_HP){ this.HP=_HP; } function Magic_monkey(_type,_home,arr,_HP){ //Monkey.call(this,_type,_home) Monkey.apply(this,[_type,_home]) Hero.call(this,_HP) this.skill=arr; } var wukong=new Magic_monkey('猴子','花果山',['七十二变','筋斗云'],1000) // alert(wukong.home); // alert(wukong.type); // alert(wukong.skill); alert(wukong.HP); wukong.say(); </script>
3、创建对象的基本模式?
new Object()
普通创建对象的方法,缺陷:
- 如果创建多个对象会比较繁琐,效率低
- 实例与原型之间,没有任何办法,可以看出有什么联系。
1 <script> 2 var people1=new Object(); 3 people1.name='孙悟空'; 4 people1.weapon='金箍棒'; 5 //this是指的当前作用域下的对象,注意和谁调用这个方法有关,和在哪定义没啥关系 6 //这里也可以简单理解为this就指的这个函数属于谁,属于谁this就是指的谁 7 people1.run=function(){ 8 return this.name+'的武器是'+this.weapon 9 } 10 alert(people1.name) 11 alert(people1.run()) //注意方法的调用需要加() 12 13 14 </script>
4、创建对象的工厂模式?
方法 对象
在方法中实现对象的创建
- 工厂模式:使用创建并返回特定类型的对象的工厂函数(其实就是普通函数,没啥区别,只是叫法不同)
- 创建过程类似于工厂生产产品的过程,即:原材料--加工--产品...
- 解决了多次重复创建多个对象的麻烦。
- 问题:
- 创建出的实例之间没有内在的联系,不能反映出它们是同一个原型对象的实例。
- 创建对象的时候没有使用 new 关键字
- 会造成资源浪费,因为每生成一个实例,都增加一个重复的内容,多占用一些内存。
1 <script> 2 //工厂模式 3 function creatPeople(name,weapon){ 4 var people=new Object() //可以类比为加工对象的原材料 5 people.name=name; 6 people.weapon=weapon; 7 people.run=function(){ 8 return this.name+'的武器是'+this.weapon 9 } //以上步骤可以类比为加工对象的过程 10 return people //注意一定要讲创建的对象返回 11 //可以类比为产品加工完毕出厂的工作 12 } 13 var wukong=creatPeople('孙悟空','金箍棒'); 14 var bajian=creatPeople('猪八戒','钉耙'); 15 //alert(wukong.run()) 16 //alert(bajian.run()) 17 //new 关键字 18 function fun(){ 19 alert(this) 20 } 21 fun() 22 new fun() 23 </script>
5、创建对象的构造函数模式?
方法 是 对象 构造函数
- new 调用的函数为构造函数,构造函数和普通函数区别仅仅在于是否使用了new来调用。
- 所谓“构造函数”,就是专门用来生成“对象”的函数。它提供模板,作为对象的基本结构。
- 构造函数内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
- instanceof 验证原型对象与实例对象之间的关系。
- 使用call和apply方法实现对象的冒充
- 问题:浪费内存--使用构造函数每生成一个实例,都增加一个重复的内容,多占用一些内存。这样既不环保,也缺乏效率。
1 <script> 2 //构造函数模式 3 //注意:构造函数不需要使用 return语句返回对象,它的返回是自动完成的 4 function People(name,weapon){ 5 this.name=name; 6 this.weapon=weapon; 7 this.run=function(){ 8 return this.name+'的武器是'+this.weapon 9 } 10 } 11 var wujing=new People('沙悟净','禅杖'); 12 alert(wujing.run()) 13 </script>
6、创建对象的(Prototype)原型模式?
共享
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。可以把那些不变的属性和方法,直接定义在prototype对象上。
- prototype方式定义的方式,函数不会拷贝到每一个实例中,所有的实例共享prototype中的定义,节省了内存。
- Prototype模式的验证方法
- isPrototypeOf()这个方法用来判断,某个proptotype对象和某个实例之间的关系。
- hasOwnProperty()每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。
- in运算符in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。in运算符还可以用来遍历某个对象的所有属性。
- 对象的constructor属性用于返回创建该对象的构造函数.(注:了解即可)
在JavaScript中,每个具有原型的对象都会自动获得constructor属性。
- 原型方式的问题:
- 构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值
- 属性指向的是对象,而不是函数时。函数共享不会造成问题,但对象却很少被多个实例共享,如果共享的是对象就会造成问题。
1 <script> 2 //原型模式 3 function Peopleobj(){} 4 Peopleobj.prototype.name='喽啰'; 5 Peopleobj.prototype.weapon='大刀'; 6 Peopleobj.prototype.run=function(){ 7 return this.name+'的武器是'+this.weapon 8 } 9 var monster_1=new Peopleobj() 10 var monster_2=new Peopleobj() 11 //alert(monster_1.constructor) 12 //这种写法和前面的方式在使用上基本相同,注意是基本 13 function Monster(){} 14 Monster.prototype={ 15 constructor: Monster, //此外强制指回Monster 16 name:'喽啰', //原型字面量方式会将对象的constructor变为Object, 17 weapon:'大刀', 18 job:['巡山','打更'], 19 run:function() {return this.name+'的工作是'+this.job } 20 } 21 var monsterA=new Monster() 22 monsterA.job.push('砍柴') 23 var monsterB=new Monster() 24 monsterB.job.push('挑水') 25 alert(monsterA.job) 26 alert(monsterB.job) 27 //alert(monsterA.constructor) 28 29 30 </script>
7、创建对象的构造函数和原型组合模式?
构造函数 原型
这是目前最为常用的创建对象的方式。
这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。
此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。
在所接触的JS库中,jQuery类型的封装就是使用组合模式来实例的!!!
1 <script> 2 function Monster(){} 3 Monster.prototype={ 4 constructor: Monster, 5 name:'喽啰', 6 job:['巡山','打更'], 7 run:function() {return this.name+'的工作是'+this.job } 8 } 9 //构造函数和原型组合模式 10 function Monster(name,arr){ 11 constructor: Monster, 12 this.name=name 13 this.job=arr 14 } 15 Monster.prototype={ 16 run:function() {return this.name+'的工作是'+this.job } 17 } 18 var monsterI=new Monster('小旋风',['巡山','打更','砍柴']) 19 var monsterII=new Monster('小钻风',['巡山','打更','挑水']) 20 alert(monsterI.run()) 21 alert(monsterII.run()) 22 </script>
8、创建对象的动态原型方法?
构造函数 原型 封装
动态原型方法的基本想法与混合的构造函数原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。
组合模式中实例属性与共享方法(由原型定义)是分离的,这与纯面向对象语言不太一致;动态原型模式将所有构造信息都封装在构造函数中,又保持了组合的优点。
其原理就是通过判断构造函数的原型中是否已经定义了共享的方法或属性,如果没有则定义,否则不再执行定义过程。该方式只原型上方法或属性只定义一次,且将所有构造过程都封装在构造函数中,对原型所做的修改能立即体现所有实例
1 <script> 2 //动态原型模式 3 function MonsterGo(name,arr){ 4 this.name=name 5 this.job=arr 6 if (typeof this.run!= "function") 7 // {alert('对象初始化') 8 MonsterGo.prototype.run=function(){ 9 return this.name+'的工作是'+this.job 10 } 11 // alert('初始化结束') 12 } 13 } 14 var monsterI=new MonsterGo('小旋风',['巡山','打更','砍柴']) 15 var monsterII=new MonsterGo('小钻风',['巡山','打更','挑水']) 16 var monsterI2=new MonsterGo('小旋风',['巡山','打更','砍柴']) 17 var monsterII2=new MonsterGo('小钻风',['巡山','打更','挑水']) 18 // alert(monsterI.run()) 19 // alert(monsterII.run()) 20 </script>
9、继承的实现:对象冒充(构造函数绑定)?
call apply
原理如下:使用对象冒充(call或apply方法)(实质上是改变了this指针的指向)继承基类。
1 <script> 2 function Monkey(_type,_home){ 3 this.type=_type; 4 this.home=_home; 5 this.say= function() { 6 alert('我是快乐的小猴子,家住'+this.home) 7 }; 8 } 9 10 function Hero(_HP){ 11 this.HP=_HP; 12 } 13 14 function Magic_monkey(_type,_home,arr,_HP){ 15 //Monkey.call(this,_type,_home) 16 Monkey.apply(this,[_type,_home]) 17 Hero.call(this,_HP) 18 this.skill=arr; 19 } 20 var wukong=new Magic_monkey('猴子','花果山',['七十二变','筋斗云'],1000) 21 // alert(wukong.home); 22 // alert(wukong.type); 23 // alert(wukong.skill); 24 alert(wukong.HP); 25 wukong.say(); 26 27 </script>
10、继承的实现:原型链?
父类 对象 赋值 子类 原型
原型链继承:原型的方式:父类的对象赋值给子类的原型
这种方法更常见,使用prototype属性。
- prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
- 原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
- 子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
1 <script> 2 //原型链继承 3 function Monkey(){} 4 Monkey.prototype.type='猴子'; 5 Monkey.prototype.say=function(){alert('我是快乐的猴子')} 6 7 function Magicmonkey(){} 8 //将Magicmonkey的prototype对象指向一个Monkey的实例。 9 //相当于删除了prototype 对象原先的值,然后赋予一个新值。 10 //不能继承多个类,后边的会覆盖前边的 11 Magicmonkey.prototype=new Monkey(); 12 Magicmonkey.prototype.skill='法术'; 13 var sunWukong=new Magicmonkey() 14 alert(sunWukong.type) 15 sunWukong.say() 16 alert(sunWukong.skill) 17 18 </script>
11、继承的实现:混合方式?
对象冒充 原型链
混合方式
我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。
对象冒充的方式无法继承原型方法
12、js中继承的常见三种方式?
对象冒充 原型链 混合方式
实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。所以大家看参考书的时候会发现很多种实现继承的方式,这里我们介绍最常用的几种。
- 对象冒充(构造函数绑定):
原理如下:使用对象冒充(call或apply方法)(实质上是改变了this指针的指向)继承基类。
- 原型链
这种方法更常见,使用prototype属性。
- prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
- 原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
- 子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
- 混合方式
我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。
13、js中如何实现多重继承?
对象冒充
1 <script> 2 function Monkey(_type,_home){ 3 this.type=_type; 4 this.home=_home; 5 this.say= function() { 6 alert('我是快乐的小猴子,家住'+this.home) 7 }; 8 } 9 10 function Hero(_HP){ 11 this.HP=_HP; 12 } 13 14 function Magic_monkey(_type,_home,arr,_HP){ 15 //Monkey.call(this,_type,_home) 16 Monkey.apply(this,[_type,_home]) 17 Hero.call(this,_HP) 18 this.skill=arr; 19 } 20 var wukong=new Magic_monkey('猴子','花果山',['七十二变','筋斗云'],1000) 21 // alert(wukong.home); 22 // alert(wukong.type); 23 // alert(wukong.skill); 24 alert(wukong.HP); 25 wukong.say(); 26 27 </script>
14、js的构造函数中的“constructor: Monster”是什么意思?
强制 指回 对象
1 <script> 2 //原型模式 3 function Peopleobj(){} 4 Peopleobj.prototype.name='喽啰'; 5 Peopleobj.prototype.weapon='大刀'; 6 Peopleobj.prototype.run=function(){ 7 return this.name+'的武器是'+this.weapon 8 } 9 var monster_1=new Peopleobj() 10 var monster_2=new Peopleobj() 11 //alert(monster_1.constructor) 12 //这种写法和前面的方式在使用上基本相同,注意是基本 13 function Monster(){} 14 Monster.prototype={ 15 constructor: Monster, //此外强制指回Monster 16 name:'喽啰', //原型字面量方式会将对象的constructor变为Object, 17 weapon:'大刀', 18 job:['巡山','打更'], 19 run:function() {return this.name+'的工作是'+this.job } 20 } 21 var monsterA=new Monster() 22 monsterA.job.push('砍柴') 23 var monsterB=new Monster() 24 monsterB.job.push('挑水') 25 alert(monsterA.job) 26 alert(monsterB.job) 27 //alert(monsterA.constructor) 28 29 30 </script>
二、内容在总结中
一、创建对象的方法
本质上都是把"属性"和"方法",封装成一个对象
创建对象的基本模式
- 普通创建对象的方法,缺陷:
- 如果创建多个对象会比较繁琐,效率低
- 实例与原型之间,没有任何办法,可以看出有什么联系。
工厂模式
- 工厂模式:使用创建并返回特定类型的对象的工厂函数(其实就是普通函数,没啥区别,只是叫法不同)
- 创建过程类似于工厂生产产品的过程,即:原材料--加工--产品...
- 解决了多次重复创建多个对象的麻烦。
- 问题:
- 创建出的实例之间没有内在的联系,不能反映出它们是同一个原型对象的实例。
- 创建对象的时候没有使用 new 关键字
- 会造成资源浪费,因为每生成一个实例,都增加一个重复的内容,多占用一些内存。
构造函数模式
- new 调用的函数为构造函数,构造函数和普通函数区别仅仅在于是否使用了new来调用。
- 所谓“构造函数”,就是专门用来生成“对象”的函数。它提供模板,作为对象的基本结构。
- 构造函数内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。
- instanceof 验证原型对象与实例对象之间的关系。
- 使用call和apply方法实现对象的冒充
- 问题:浪费内存--使用构造函数每生成一个实例,都增加一个重复的内容,多占用一些内存。这样既不环保,也缺乏效率。
(Prototype)原型模式
Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。可以把那些不变的属性和方法,直接定义在prototype对象上。
- prototype方式定义的方式,函数不会拷贝到每一个实例中,所有的实例共享prototype中的定义,节省了内存。
- Prototype模式的验证方法
- isPrototypeOf()这个方法用来判断,某个proptotype对象和某个实例之间的关系。
- hasOwnProperty()每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。
- in运算符in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。in运算符还可以用来遍历某个对象的所有属性。
- 对象的constructor属性用于返回创建该对象的构造函数.(注:了解即可)
在JavaScript中,每个具有原型的对象都会自动获得constructor属性。
- 原型方式的问题:
- 构造函数没有参数。使用原型方式,不能通过给构造函数传递参数来初始化属性的值
- 属性指向的是对象,而不是函数时。函数共享不会造成问题,但对象却很少被多个实例共享,如果共享的是对象就会造成问题。
构造函数和原型组合模式
这是目前最为常用的创建对象的方式。
这种概念非常简单,即用构造函数定义对象的所有非函数属性,用原型方式定义对象的函数属性(方法)。结果是,所有函数都只创建一次,而每个对象都具有自己的对象属性实例。
此外,组合模式还支持向构造函数传递参数,可谓是集两家之所长。
在所接触的JS库中,jQuery类型的封装就是使用组合模式来实例的!!!
动态原型方法
动态原型方法的基本想法与混合的构造函数原型方式相同,即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。
组合模式中实例属性与共享方法(由原型定义)是分离的,这与纯面向对象语言不太一致;动态原型模式将所有构造信息都封装在构造函数中,又保持了组合的优点。
其原理就是通过判断构造函数的原型中是否已经定义了共享的方法或属性,如果没有则定义,否则不再执行定义过程。该方式只原型上方法或属性只定义一次,且将所有构造过程都封装在构造函数中,对原型所做的修改能立即体现所有实例
继承继承的相关概念
- 这里的继承和我们现实生活的中儿子继承父亲财产的这种关系虽然有相似的地方,但本质其实不一样;
- 举一个简单的例子理解继承的含义:
-
猴子--会法术的猴子--孙悟空;
- 会法术的猴子和猴子是我们这里所说的继承关系;
- 会法术的猴子是猴子的一种,即猴子是会法术的猴子的类型;
- 孙悟空是会法术的猴子的一个实例,即会法术的猴子是孙悟空的类;
- 孙悟空即使会法术的猴子的一种,也是猴子的一种,这种关系就和我们接下来要讲的继承是一个道理;
- 在程序里我们将猴子叫做父类(超类,基类),会法术的猴子是他的子类(子类型,派生类),会法术的猴子继承了猴子的所有特征;
- 会法术的猴子是孙悟空的类;孙悟空是会法术的猴子的实例;
- 一旦确定了两个类的继承关系,就包含以以三个意思:
- 子类的实例可以共享父类的方法
- 子类可以覆盖或扩展父类的方法
- 子类和父类都是子类实例的类型
二、继承的实现
实现继承的方式不止一种。这是因为 JavaScript 中的继承机制并不是明确规定的,而是通过模仿实现的。所以大家看参考书的时候会发现很多种实现继承的方式,这里我们介绍最常用的几种。
- 对象冒充(构造函数绑定):
原理如下:使用对象冒充(call或apply方法)(实质上是改变了this指针的指向)继承基类。
- 原型链
这种方法更常见,使用prototype属性。
- prototype 对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
- 原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 prototype 属性。
- 子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。
- 混合方式
我们曾经讲解过创建类的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承 prototype 对象的方法。