日期:2017-12-26 by:simoon
javaScript中一切都是对象,对象的来源于null。
什么是类?
类:具有一些特点,就是属性(property)。同时具有一些行为,就是方法e(method);
类是某一类具有相同的特性。而其中的某一个就是对象的实例。
那么如何理解面向过程和面向对象呢。
举一个现实中的例子:
比如说:我叫小明去帮我买个汉堡包这个例子。
面向过程如下:
//面向过程:
console.log("我喊小明过来");
console.log("小明过来了");
console.log("给你十块钱去KFC给我买汉堡,记得找零钱");
console.log("小明拿着钱下去去肯德基");
console.log("排队,跟营业员沟通");
console.log("给钱,等待");
console.log("营业员找钱,准备食物");
console.log("小明收好零钱,拿好汉堡,准备回来");
console.log("把汉堡给我,给我零钱);*/
面向对象如下:
//面向对象
var tech={
name:"李响",
act1:function(){
console.log("我喊小明过来");
},
act2:function(){
console.log("给小明十块钱去KFC给我买汉堡,记得找零钱");
},
act3:function(){
console.log("拿汉堡,收好零钱");
}
};
var xiaoming={
name:"小明",
age:18,
act1:function(){
console.log("被老师喊过来");
},
act2:function(){
console.log("拿钱去KFC");
},
act3:function(){
console.log("排队");
}
var saler={
name:"小花",
age:20,
act1:function(){
console.log("跟小明眉来眼去,沟通");
},
act2:function(){
console.log("收钱准备食物");
},
act3:function(){
console.log("找零,给食物");
},
}
javaScript中是自带了很多内置对象的,比如:
var arr = new Array();
var date = newDate();
什么是对象的属性呢?就是它的特点,比如arr就具有长度的属性.
arr.lenght
什么是对象的方法呢?比如:
arr.sort();
arr.join();
arr.reverse();
这样就很好理解javascript中的对象的属性和方法了,属性就是具有的特征,而对象就是一种行为。
那么如何自己创建一个对象呢?
字面量创建:
1: var 对象名 = {属性1:方法1,属性2:方法2}
2: var 对象名 = {}
2-1: 对象名.属性1 = 方法1;
2-1: 对象名.属性2 = 方法2;
比如说:
var obj={};
obj.name="小花";
obj.act=function(){
alert(1);
}
obj.cc=function(){
name:"小红";
aa:function(){
alert(this.name);
}
}
这样的obj对象就具有一个name属性,一个sct的方法了,一个cc方法。
那么问题出来了,这里的this指向谁??
回顾:在单独的函数中,匿名函数,this指向window,非匿名函数指向事件源。
如果出现函数的嵌套,这时候this指向离哪个近,就指向哪个。
那么如何改变this的指向呢?方法有两个:
- call() 方法
- apply()方法
call(a,b,c) 方法可以传多个参数,第一个方法是this的指向,后面的是传入的参数。
apply(a,[b,c])方法传入一个参数和一个数组,如果不是数组,将会报错。
如果什么都不传,相当于函数调用
比如说:
function fn(a,b){
console.log(this);
console.log(a+"+"+b+"="+(a+b));
}
fn.call(5,7,8)
控制台输出:5和7+8=15;
function fn(a,b,c){
console.log(this);
console.log(a,b,c);
}
fn.apply(6,[5,6,7]);
控制台输出:6和5 6 7
利用上面的特点,我们可以求数组最大值。实现代码如下:
console.log(Math.max.apply(Math,[1,3,55,4]));
···
原理是,apply()没有改变指向,依然指向Math,
关于与保留this的问题
<body>
<button id="btn">按钮</button>
</body>
<script>
var btn = document.getElementById('btn');
btn.onclick = function(){
function fn1(){
console.log(this.innerHTML);
}
}
fn1();
</script>
一段这样的代码,控制台输出:Window undefined。为什么呢?
因为这时候this指向的是window。如果想指向btn,那么就需要预保留this。
代码如下:
<body>
<button id="btn">按钮</button>
</body>
<script>
var btn = document.getElementById('btn');
btn.onclick = function(){
var _this = this;//通过_this预保留
function fn1(){
console.log(_this,_this.innerHTML);
}
fn1();
}
</script>
我们可以通过new来创建对象
<body>
<script>
var obj = new Object();
obj.name = "小明";
obj.act = function(){
alert(this.name);
}
obj.act();
</script>
</body>
但是这样的创建太麻烦了,所以我们需要工厂函数创建对象。
具体如下:这样就可以重用了。
<body>
<script>
function createPerson(n,a){
var obj = new Object();
obj.name = n;
obj.age = a;
obj.showName = function(){
alert(this.name);
}
// 出厂
return obj;
}
var p1 = createPerson("小花",18);
var p2 = createPerson("小明",16);
p1.showName();
p2.showName();
console.log(p1.age);
console.log(p2.age);
</script>
</body>
当new一个对象时会发生什么呢?
会创建一个实例对象,这是的this指向实例对象。函数会有一个默认的返回值,就是这个对象。
<body>
<script>
function CreatePerson(n,a){
this.name=n;
this.age=a;
this.showName=function(){
alert(this.name);
}
}
var p1 = new CreatePerson("小花",19);
p1.showName();
var p2 = new CreatePerson("小明",16);
p2.showName();
</script>
</body>
构造函数在解决了上面所有问题,同时为实例带来了类型,但可以注意到每个实例printName方法实际上作用一样,但是每个实例要重复一遍,大量对象存在的时候是浪费内存。
那么如何解决呢?
- 任何函数使用new都是表达式就是构造函数(工厂函数)
- 每一个函数都会添加一个原型
- 每个对象都有一个内部属性 proto(规范中没有指定这个名称,但是浏览器都这么实现的) 指向其类型的prototype属性,类的实例也是对象,其proto属性指向“类”的prototype。
比如有一个代码
function Person(nick, age){
this.nick = nick;
this.age = age;
this.sayName = function(){
console.log(this.nick);
}
}
var p1 = new Person();
这段代码中的sayname就是每次new 对象都会重复的方法。

通过这个原理,我们可以抽象重复。
- 所有函数都会通过原型链来引用类型的prototype
- prototype相当于特定类型所有实例都可以访问到的一个公共容器
- 我们可以把重复的东西放到prototype中。
这时候,把重复的方法挂在到prototype中,代码如下:
function Person(nick, age){
this.nick = nick;
this.age = age;
}
Person.prototype.sayName = function(){
console.log(this.nick);
}
var p1 = new Person();
p1.sayName();
这时候,相对应的关系如下:

再写个小例子
<script>
function CreatPerson(n,a){
this.name = n;
this.age = a;
this.showName=function(){
alert(this.name);
}
}
var p1=new CreatePerson("小明",16);
p1.showName();
p1.showAge=function(){
alert(this.age);
}
var p2=new CreatePerson("小花",19);
p2.showName();
</script>
这里的showName方法就重复了,如何使用原型链来解决呢?
代码如下:
<body>
function CreatPerson(n,a){
this.name = n;
this.age = a;
}
CreatPerson.prototype.showName = function(){
alert(this.name);
}
var p1 = new CreatPerson("小花",18);
p1.showName();
var p1 = new CreatPerson("小花花",16);
p1.showName();
alert(p1.age);
</script>
</body>
最后尝试封装一个数组求和的函数,实现代码如下:
<body>
<script>
Array.prototype.sum = function(){
var result = 0;
for(var i=0;i<this.length;i++){
result += this[i];
}
return result;
}
var arr = new Array(1,2,3,44);
console.log(arr.sum());
</script>
</body>
THE END
网友评论