js面向对象2
# 构造函数和原型
# 创建对象的三种方式
利用
new Object()
创建对象var a = new Object();
1利用 对象字面量创建对象
var a = {};
1利用构造函数
function Star(){ this.uname = uname; this.age = age; this.sing = function(){ console.log('sing..'); } } var yuadh = new Star('yuadh',20);
1
2
3
4
5
6
7
8
# 构造函数
构造函数 是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面
过程
- 在内存中创建一个新的空对象
- 让 this 指向这个新的对象
- 执行构造函数里面的代码,给这个新对象添加属性和方法
- 返回这个新对象(所以构造函数里面不需要return)
# 实例成员和静态成员
实例成员就是构造函数内部通过this添加的成员 , 示例成员只能通过实例化的对象来访问
静态成员 在构造函数本身上添加的成员
Star.name = 'yuadh'; console.log(Star.name);
1
2
# 构造函数原型 prototype
构造函数通过原型分配的函数时所有对象所共享的
每一个构造函数都有一个 prototype
属性,指向另一个对象。注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有
注意:我们可以把那些不变的方法,直接定义在 prototype
对象上,这样所有对象的实例就可以共享这些方法
**原型对象:**一个对象,prototype 为原型对象。作用是 共享方法
Star.prototype.sing = function(){
console.log('sing...');
}
2
3
# __proto__
和prototype的关系
每个示例化对象都会有一个 __proto__
属性指向构造函数的 prototype 原型对象,之所以我们对象可以使用构造函数 prototype 原型对象的属性和方法,就是因为对象有 __proto__
原型的存在
__proto__
对象原型和原型对象 prototype 是等价的__proto__
对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线,但它是一个非标准属性
# 原型 constructor
构造函数
constructor
为构造函数 ,用来 __proto__
和 prototype
指回构造函数本身
Star.prototype = {
constructor: Star, // 修改prototype对象后 指会原来的构造函数
sing: function(){
console.log('singgg');
},
moive: function(){
console.log('moiveee');
}
}
2
3
4
5
6
7
8
9
# 原型链
console.log(led.__proto__);
console.log(Star.prototype);
console.log(Star.prototype.__proto__);
console.log(Object.prototype);
console.log(Object.prototype.__proto__);
null;
2
3
4
5
6
7
8
9
10
11
- 当访问一个对象的属性时,首先查找这个对象自身有没有改属性
- 如果没有就查找他的原型(
__proto__
指向的prototype
) - 如果还没有查找原型对象的原型 (Object)
- 一致找到 null 为止
# 扩展内置对象
可以通过原型对象,对原来的内置对象进行扩展自定义的方法
//对原型对象的扩展 , 不推荐使用覆盖重新指向的方法
Array.prototype.sum = function(){
var sum = 0;
for(var i = 0;i < this.length;i++){
sum+=this[i];
}
return sum;
}
console.log(arr.sum());
2
3
4
5
6
7
8
9
# call()方法
可以调用函数
function fn(x,y){ console.log(x+y); } fn.call();//调用
1
2
3
4可以改变函数的
this
指向function fn(x,y){ console.log(this); console.log(x+y); } var y = { name : 'yuadh'; } fu.call(y,3,4);//改变了指向
1
2
3
4
5
6
7
8
利用call() 函数实现继承属性
function Father(uname,age){
this.uname = uname;
this.age = age;
}
function Son(uname,age,score){
Father.call(this,uname,age);
this.score = score;
}
var son = new Son('yuadh',21,44);
2
3
4
5
6
7
8
9
# 原型对象继承原理
父类的原型对象
Father.prototype.money = function(){
console.log('make money');
}
2
3
子类的原型对象
Son.prototype.exam = function(){
console.log('examing...');
}
2
3
上面实现了属性的继承,但是没有对原型对象 实现继承
Son.prototype = Father.prototype;
此解决了子类对父类的原型对象的继承 ,但是父类的原型对象会出现问题
因为指向的是同一内存空间
解决方法
Son.prototype = new Father();
Son.prototype.constructor = Son;
//需要在上两个语句后面添加子类自身的原型对象属性方法,不然会被覆盖
Son.prototype.exam = function(){
console.log('examing...');
}
2
3
4
5
6
因为 Father 的实例化对象里有 __proto__
属性,且实例化对象对父类原型对象没有影响。对子类的构造方法进行了覆盖,需要将构造函数重新指向子类
# ES5新增方法
- 数组方法
- 字符串方法
- 对象方法
# 数组方法
迭代方法 :
forEach()
map()
filter()
some()
every()
forEach
array.forEach(function(currentVale,index,arr))
currentValue
数组当前项的值index
数组当前项的索引arr
数组对象本身
例子使用:
var arr = [1,2,3];
var sum = 0;
arr.forEach(function(value,index,array){
sum += value;
})
console.log(sum);
2
3
4
5
6
filter
array.filter(function(currentVale,index,arr))
返回偶数元素的例子
var arr = [12,4,5,7,8];
var newArr = arr.filter(function(value,index){
return value%2 === 0;
})
console.log(newArr);
2
3
4
5
soome
array.some(function(currentVale,index,arr))
查找满足条件的元素是否存在 ,存在返回 true 不存在返回 false
var arr = ['yuadh','pink','me'];
var flagx = arr.some(function(value){
return value == 'yuadh';
})
2
3
4
当查询到一个满足条件的元素就会停止循环查找
# 综合使用
<div class="search">
按照价格查询: <input type="text" class="start"> - <input type="text" class="end"> <button class="search-price">搜索</button> 按照商品名称查询: <input type="text" class="product"> <button class="search-pro">查询</button>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>产品名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 利用新增数组方法操作数据
var data = [{
id: 1,
pname: '小米',
price: 3999
}, {
id: 2,
pname: 'oppo',
price: 999
}, {
id: 3,
pname: '荣耀',
price: 1299
}, {
id: 4,
pname: '华为',
price: 1999
}, ];
var tbody = document.querySelector('tbody');
var search_button = document.querySelector('.search-price');
var start_text = document.querySelector('.start');
var end_text = document.querySelector('.end');
var product = document.querySelector('.product');
var search_pro = document.querySelector('.search-pro');
showres(data);
function showres(data) {
tbody.innerHTML = "";
data.forEach(function(value, index) {
var th = document.createElement('tr');
th.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>'
tbody.appendChild(th);
})
}
search_button.addEventListener('click', function() {
var newdata = data.filter(function(value) {
return value.price >= start_text.value && value.price <= end_text.value;
})
showres(newdata);
});
search_pro.addEventListener('click', function() {
var newArr = [];
data.some(function(value) {
if (product.value == value.pname) {
newArr.push(value);
return true;
}
})
showres(newArr);
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# trim
去除字符串两侧空格
var str = ' an dy';
var newStr = str.trim();
2
# Object.keys()
获取对象的属性返回一个数组
var obj = {
id: 4,
pname: '华为',
price: 1999
}
var arr = Object.keys(obj);
arr.forEach(function(value){
console.log(value);
})
2
3
4
5
6
7
8
9
# Object.defineProperty()
Object.defineProperty(obj,prop,descriptor);
第三个参数 descriptor 以对象形式 {} 书写
value : 设置属性的值,默认值为 undefined
writable : 值是否可以重写 , true | false
enumerate: 目标属性是否可以被枚举,true | false (是否允许被遍历,默认不能)
configurable:目标属性是否可以被删除或是否可以再次修改特性,true | false
(设置这个属性后不允许删除或修改属性)