这里写目录标题
面向对象中的各个方法
1. __proto__
__proto__
是构造函数中的一个原型对象,通过 prototype 获取- 基于构造函数创建对象后,每个对象都有一个私有的 proto 属性,指向兑现构造函数的原型对象
- 基于上面两点,构造函数 prototype 属性与对象 proto 属性指向的是同一个对象
<script>
function Car(brand){
this.brand=brand //实例属性
}
console.log(Car.prototype);
var c1 = new Car();
console.log(c1.__proto__);
var c2 = new Car();
// console.log(c2.__proto__);
console.log(Object.getPrototypeOf(c2));//Object.getPrototypeOf() 方法返回指定对象的原型
console.log(c1.__proto__ === c2.__proto__); // 指向同一个内存地址
</script>
2. call
-
call 可以调用函数
-
还可以修改 this 的指向,call 方法第一个参数,用于替代函数中的 this ,第二参数开始,才是参数列表,使用 call() 的时候,参数一是修改后的 this 指向,参数2,参数3,参数…使用逗号隔开链接
-
继承的主要目的是代码重用
-
前面使用 class 方式创建的类,可以非常轻松的实现继承,就跟其他的面向对象编程语言一样,如 c++ ,Java 等
-
class 语法只是 js 中的一种语法糖,其本质还是使用了基于原型的构造函数
-
使用 call 方法,就可以实现构造函数之间的继承
<script> function Father(name,age){ this.name = name this.age = age } function Son(name,age){ Father.call(this,name,age) } var s1 = new Son('李白',53) var s2 = new Son('杜甫',50) console.log(s1) console.log(s2) console.log('---------------------------') function Father(name,age,height,weight,gender){ this.name = name this.age = age this.height = height this.weight = weight this.gender = gender } function Chinese(name,age,height,weight,gender,hukou){ // this.name = name // this.age = age // this.hukou = hukou Father.call(this,name,age,height,weight,gender) this.hukou =hukou } var c1 =new Chinese('ysx',18,170,88,'男','河北保定') console.log(c1) </script>
3. constructor
原型对象通过 constructor 指回构造函数
- 对象原型 (
__proto__
) 和 构造函数 (prototype
) 原型函数里面都有一个constructor
属性,constructor 我们称为构造函数,因为它指回构造函数的本身
<script>
function Car(brand) {
this.brand = brand //实例属性
}
// Car.prototype.drive = function() {
// console.log('骑着我的小毛驴')
// }
// Car.prototype.start = function() {
// console.log('start')
// }
// Car.prototype.stop = function() {
// console.log('stop')
// }
// Car.prototype.run = function() {
// console.log('run')
// }
Car.prototype = {
/*只这样写会少一个方法,因为这种方法只是重写,没有回调指向,
* 所以我们要用constructor方法回调
* */
constructor:Car,
drive:function(){
console.log('骑着我的小毛驴')
},
start:function(){
console.log('start')
},
stop:function(){
console.log('stop')
},
run:function(){
console.log('run')
}
}
console.log(Car.prototype);
var c1 = new Car()
c1.drive()
</script>
4.原型对象
- 每一个构造函数都有一个 prototype 属性,此属性的值是一个对象,这个对象叫做当前构造函数的原型对象
- 原型对象上的所有属性和方法,构造函数中也会拥有
- 所以将方法定义到原型对象上,可以让多个构造函数的对象 (p1 p2) 共享一个方法,节省内存空间
<script>
function Preson(name,age){
this.name = name
this.age = age
this.run = function(){
console.log('run')
}
}
Preson.prototype.does=function(){
console.log('hello world')
}
console.log(Preson.prototype);
var p1 = new Preson('金菱玉','100000');
p1.does()
var p2 = new Preson('武陵仁','1000');
p2.does()
console.log(p1.does === p2.does)
console.log(p1.run === p2.run)
</script>
5.语法糖
- 通过构造函数的形式创建对象,是 JS 中最本质的创建对象的方式
- 通过 class 的方式创建对象,只是 JS 中的语法糖
- 开发中可以放心使用 class 方法创建对象,可以试试用插件将其编译成 ESS 语法,保证兼容性
<script>
function Person(name,age){
this.name=name
this.age = age
}
var p1 = new Person('yhb',18);
var p2 = new Person('hapi',19);
console.log(p1);
console.log(p2);
/*
* 语法糖
*/
class car{
constructor(name,born) {
this.name = name
this.born = born
}
}
var h = new car('五岳',1988);
console.log(h);
</script>
6. 类的继承 class
-
super 就代表了父类的构造函数
<script> class Dog{ constructor(name,age){ this.name = name this.age = age } speak(){ console.log('汪汪汪') } } class Hshiqi extends Dog{ constructor(name,age,levl) { // super 就代表了父类的构造函数 super(name,age) this.levl = levl } does(){ console.log('拆家') } speak(){ console.log('嗷嗷嗷') } } var h = new Hshiqi('哈皮',18,8) // h.speak() // h.does() console.log(h) </script>
7.静态成员
- 构造函数中成员分为两种: 实例成员 和 静态成员,我们下面以属性为例为例
- 通过 new 关键字创建的就是构造函数中的实例
- 所谓的实例属性就是只能同各国构造函数的实例访问
- 静态属性只能通过类名,属性名称的方式访问: 使用类名.属性访问 访问
- 静态成员是在构造函数本身上添加的成员,与具体的对象无关
<script>
function Car(brand){
this.brand=brand //实例属性
//Car.count == undefined还可以写成 ! 形式
if(!Car.count){
Car.count = 0 //静态属性 static
}
Car.count++
}
var c1 = new Car('五菱之光');
console.log(Car.count)
var c2 = new Car('奔驰');
console.log(Car.count)
var c3 = new Car('劳斯莱斯');
console.log(Car.count)
// console.log(c1.brand);
// console.log(c1.count);
</script>
8.关系
- 任何对象都有原型对象,也就是 prototype 属性,任何原型对象也是一个对象,该对象就有
__proto__
属性,这样一层一层往上找,就形成了一条链,我们称此为原型链 - 查找机制:
- 当访问一个对象的属性 (包括方法) 时,首先查找这个对象自身有没有该属性
- 如果没有就查找它的原型 (也就是
__proto__
指向的 prototype 原型对象) - 如果还没有就查找原型对象的原型 (Object 的原型对象)
- 以此类推一直找到Obedct 为止 (null)
__proto__
对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线
<script>
function Car(brand) {
this.brand = brand //实例属性
}
// //构造函数的 prototype 属性指向原型对象
// console.log(Car.prototype)
// // 原型对象的 constructor 属性指向构造函数
// console.log(Car.prototype.constructor)
// var c1=new Car()
// console.log(c1.__proto__.__proto__)
Car.prototype.__proto__.run = function() {
console.log('run')
}
var c1 = new Car()
c1.run()
</script>
9.this
- 当在全局创建一个 this 指向时,他的指向位置就是 Window
- 在创造函数中创建一个 this 指向时,他的指向是我们创建的构造函数中的对象实例
- 在构造函数的原型对象中, this 同样指代构造函数中的对象实例
<script>
// function f1(){
// console.log(this)
// }
// f1()
function Car(brand){
this.brand = brand;
console.log(this);
}
Car.prototype.run=function(){
console.log(this);
}
var c1 = new Car('五菱宏光');
var c2 = new Car('长城皮卡');
console.log(c1 === c2);
c1.run()
c2.run()
</script>
10.数组
<script>
var arr = new Array()
console.log(arr.__proto__);
console.log(Array.prototype);
var arr1=[]
console.log(arr1.__proto__);
function sum(arr){
sdadada
}
sum(arr)
</script>
11. forEach 遍历数组
- forEach 相当于数组遍历的 for循环 没有返回值
<script>
arr.forEach(function(value, index, array) {
参数一是:数组元素
参数二是:数组元素的索引
参数三是:当前的数组
})
</script>
案例:
<script>
var arr = [1, 3, 4, 5, 6]
arr.forEach(function(currentValue,index,arr){
console.log(currentValue,index,arr);
})
Array.prototype.sum=function(){
//console.log(this);
var sum=0;
this.forEach(function(item){
// console.log(item);
sum+=item
})
return sum
}
console.log(Array.prototype);
var arr=[2,3,4]
// arr.sum()
console.log(arr.sum());
console.log([4,5,6].sum());
</script>
12.some
- some 查找数组中是否有满足条件的元素
- some的各个参数:
- 参数1:数组元素
- 参数2:数组元素的索引
- 参数3:当前的数组
- 返回值 : 数组中至少一个元素通过回调函数的测试就会返回 true,所有元素都没通过回调函数的测试返回值才会为 false
- some 和 forEach的区别:
- 如果查询数组中唯一的元素, 用some方法更合适,在some 里面 遇到 return true 就是终止遍历 迭代效率更高
- 在forEach 里面 return 不会终止迭代
<script>
var arr = [1, 3, 4, 5, 6]
var result = arr.some(function(value, index, arr){
return value > 3
})
console.log(result)
</script>
13. filter
filter截取数组函数
- forEach 是循环数组,filter 返回值是一个新的、由通过测试的元素组成的数组,如果没有任何数组通过测试,则返回空数组
<script>
var arr = [1, 3, 4, 5, 6]
var result = arr.filter(function(item, index, arr){
return item > 3
})
console.log(result)
</script>
14. find 和 findIndex
- find() 方法 返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined
- findIndex() 方法 返回数组中满足提供的测试函数的第一个元素的索引。如果没有找到对应元素则返回-1
<script>
var arr = [1, 3, 4, 5, 6]
//var arr = [1, 3, 2]
var result = arr.find(function(value, index, arr){
return value > 3
})
console.log(result)
var result = arr.findIndex(function(value, index, arr){
return value > 3
})
console.log(result)
</script>
15.筛选
筛选案例
- 页面加载时加载所有商品
- 用户输入了哪些数据,就按照这些条件进行筛选
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
.box{
margin: 10px 300px;
}
.header{
margin-bottom: 10px;
}
table{
border: 1px solid #000;
width: 800px;
border-collapse: collapse;
text-align: center;
}
th,td{
border: 1px solid #000;
padding: 5px 10px;
}
</style>
</head>
<body>
<div class="box">
<div class="header">
<label>最低价格</label>
<input type="text" id="start_price" />
<label>最高价格</label>
<input type="text" id="end_price" />
<label>商品名称</label>
<input type="text" id="title" />
<button id="btn_filter">筛选</button>
</div>
<table>
<thead>
<tr>
<th>编号</th>
<th>商品名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<script>
/**
* 1)页面加载时加载所有商品
* 2)用户输入了哪些数据,就按照这些条件进行筛选
* */
var btn_filter = document.querySelector('#btn_filter');
var start_price = document.querySelector('#start_price');
var end_price = document.querySelector('#end_price');
var title = document.querySelector('#title');
var data = [{
id: '001',
title: '小米10',
price: 3999
}, {
id: '002',
title: '小米8',
price: 2099
}, {
id: '003',
title: '小米7',
price: 1999
}, {
id: '004',
title: 'iPhone11',
price: 5666
}, {
id: '005',
title: 'iPhone8',
price: 3333
}, {
id: '006',
title: 'iPhone8',
price: 7566
}, {
id: '007',
title: 'oppo',
price: 1500
}, {
id: '008',
title: 'vivo',
price: 1500
}, {
id: '009',
title: '华为',
price: 820
}, {
id: '010',
title: '锤子',
price: 903
}, ];
setData(data)
function setData(pro_data) {
document.querySelector('tbody').innerHTML = ''
pro_data.forEach(function(item) {
var tr =
`
<tr>
<td>${item.id}</td>
<td>${item.title}</td>
<td>${item.price}</td>
</tr>
`
document.querySelector('tbody').insertAdjacentHTML('beforeend', tr)
})
}
btn_filter.addEventListener('click', function() {
var newData = data.filter(function(item) {
var new_start_price = start_price.value != '' ? start_price.value : 0;
var new_end_price = end_price.value != '' ? end_price.value : Infinity;
var new_title = title.value != '' ? title.value : item.title;
return item.price >= new_start_price && item.price <= new_end_price && item.title == new_title
})
console.log(newData)
setData(newData)
})
</script>
</body>
</html>
16. trim
trim方法去除字符串两端的空格
<script>
var str = ' hello '
console.log(str.trim()) //去除两端的空格
</script>
17.获取对象属性名称
- Object.keys(对象) 获取到当前对象中的属性名 ,返回值是一个数组
- Object.keys 获取的是对象中的是属性,而不是类或者构造函数
- 他一般很少用,但是想自己编写库或者框架,是需要的
<script>
var person = {
name:'yhb',
age:20
}
var keys=Object.keys(person)
console.log(keys);
//使用构造函数创建对象
function Car(){
this.name='asjkda'
this.gender='男'
}
var c1=new Car()
console.log(Object.keys(c1))
//使用class方法
class Dog{
constructor(name,age) {
this.name=name
this.age=age
}
}
var d1=new Dog()
console.log(Object.keys(d1))
</script>
18.Object.defineProperty()
- bject.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
- Object.defineProperty() 方法 应当直接在构造器对象上调用,而不是在任意一个 Object 类型的实例上调用。
- Object.defineProperty(obj, prop, descriptor) 各个参数意义:
- obj:要定义属性的对象。
- prop:要定义或修改的属性的名称或 Symbol
- descriptor:要定义或修改的属性描述符
- 重点是 descriptor 属性
- 数据描述符:主要用来描述属性的值、是否可以枚举、是否可以更改属性的值、是否可以删除属性
'use strict'
严谨模式
<script>
'use strict' //严谨模式
var obj={}
// obj.name='yhb'
// console.log(obj);
Object.defineProperty(obj,'age',{
value:'18', //在给对象添加属性时,我们默认属性为不可删,不可改
configurable:true ,//设置 configurable 属性 ,并把值设置为true ,属性可以删除
writable:true ,//设置 writable 属性 ,并设为true , 属性的值可以修改
enumerable:true //属性可以被枚举(列)出来
})
console.log(obj)
obj.age = 20 //修改 age 的值
//delete obj.age //从 obj 对象中删除 age 属性
console.log(obj);
console.log(Object.keys(obj));
Object.defineProperty(obj,'gender',{
get : function(){
return 'hello' //返回值作为我们的属性值
},
set:function(newValue) {
console.log(newValue); //存取描述
}
})
console.log(obj.gender);
obj.gender='女'
</script>
19.数组绑定
单向数组绑定
html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>单向数组绑定</title>
</head>
<body>
<div id="app">
<p>{{title}}</p>
</div>
<button>修改</button>
<script src="./vue.js"></script>
<script>
obj.title='sss'
document.querySelector('button').addEventListener('click',function(){
obj.title='你好'
})
</script>
</body>
</html>
vue.js 代码
var obj = {}
var nodes = document.querySelector('#app').children
var title_node = null
console.log(nodes);
//nodes 是伪数组 所以要转型
Array.from(nodes).forEach(function(item){
if (item.innerHTML == '{{title}}'){
title_node = item
}
})
Object.defineProperty(obj, 'title', {
set: function(newValue) {
title_node.innerHTML = newValue
}
})