JavaScript面向对象

面向对象基本概念

  • 封装:能够将一个实体的信息、功能、响应都封装到一个单独对象中的特性。

    由于JavaScript没有public、private、protected这些关键字,但是可以利用变量的作用域来模拟public和private封装特性

<script>
var Person = (function() {
    var name = '张三';
    return {
        getName: function() { 
            return name; 
        }
    }
})();

console.log(Person.name); // undefined
console.log(Person.getName()); // hello
</script>
  • 继承:在不改变源程序的基础上进行扩充,原功能得以保存,并且对子程序进行扩展,避免重复代码编写
  • 多态:允许将子类类型的指针赋值给父类类型的指针;原生JS是弱类型语言,没有多态概念

JavsScript中面向对象的一些概念:

  • 类class: ES5以前就是构造函数,ES6中有class
  • 实例instance和对象object:构造函数创建出来的对象一般称为实例instance
  • 父类和子类:JavaScript也可以称为父对象和子对象

对象属性

属性
  • Object.prototype Object 的原型对象,不是每个对象都有prototype属性
  • Object.prototype.proto 不是标准方法,不鼓励使用,每个对象都有__proto__属性,但是由于浏览器实现方式的不同,__proto__属性在chrome、firefox中实现了,在IE中并不支持,替代的方法是Object.getPrototypeOf()
  • Object.prototype.constructor:用于创建一个对象的原型,创建对象的构造函数
特性名称描述默认值
value属性的值undfined
writable是否可以修改属性的值,true表示可以,false表示不可以true
enumerable属性值是否可枚举,true表示可枚举for-in, false表示不可枚举true
configurable属性的特性是否可配置,表示能否通过delete删除属性后重新定义属性true
特性名称描述默认值
set设置属性时调用的函数undefined
get写入属性时调用的函数undefined
configurable表示能否通过delete删除属性后重新定义属性true
enumerable表示能否通过for-in循环返回属性true
方法
  • Object.prototype.toString() 返回对象的字符串表示
  • Object.prototype.hasOwnProperty() 返回一个布尔值,表示某个对象是否含有指定的属性,而且此属性非原型链继承,也就是说不会检查原型链上的属性
  • Object.prototype.isPrototypeOf() 返回一个布尔值,表示指定的对象是否在本对象的原型链中
  • Object.prototype.propertyIsEnumerable() 判断指定属性是否可枚举
  • Object.prototype.watch() 给对象的某个属性增加监听
  • Object.prototype.unwatch() 移除对象某个属性的监听
  • Object.prototype.valueOf() 返回指定对象的原始值
  • 获取和设置属性
    • Object.defineProperty 定义单个属性
    • Object.defineProperties 定义多个属性
    • Object.getOwnPropertyDescriptor 获取属性
  • Object.assign() 拷贝可枚举属性 (ES6新增)
  • Object.create() 创建对象
  • Object.entries() 返回一个包含由给定对象所有可枚举属性的属性名和属性值组成的 [属性名,属性值] 键值对的数组,数组中键值对的排列顺序和使用for…in循环遍历该对象时返回的顺序一致
  • Object.freeze() 冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象
  • Object.getOwnPropertyNames() 返回指定对象的属性名组成的数组
  • Object.getPrototypeOf 返回该对象的原型
  • Object.is(value1, value2) 判断两个值是否是同一个值 (ES6 新增)
  • Object.keys() 返回一个由给定对象的所有可枚举自身属性的属性名组成的数组,数组中属性名的排列顺序和使用for-in循环遍历该对象时返回的顺序一致
  • Object.setPrototypeOf(obj, prototype) 将一个指定的对象的原型设置为另一个对象或者null
  • Object.values 返回一个包含指定对象所有的可枚举属性值的数组,数组中的值顺序和使用for…in循环遍历的顺序一样

prototype和__proto__

对象类型prototypeproto
函数对象YesYes
普通对象NoYes
  • 只有函数对象具有prototype这个属性
  • prototype__proto__都是js在定义一个对象时的预定义属性
  • prototype 被实例的__proto__指向
  • __proto__指向构造函数的prototype
<script>
const a = function(){}
const b = {}


console.log(typeof a) // function
console.log(typeof b) // object


console.log(typeof a.prototype) // object
console.log(typeof a.__proto__)// function


console.log(typeof b.prototype) // undefined
console.log(typeof b.__proto__) // object

</script>
<script>
const Dogs = function(name) {
    this.name = name;
}

Dogs.prototype.DogName = function() {
    return this.name
}

const jinmao = new Dogs('jinmao');
console.log(jinmao); //返回对象
console.log(jinmao.DogName());//返回jinmao

</script>

原型继承

原型继承就是利用原型链来实现继承

<script>
function Summer() {
    this.SummerName = 'Sum';
}

Summer.prototype.getSummerName= function(){
    return this.SummerName;
}

function Sub () {
    this.SubNmae='SubNmae';
}

Sub.prototype = new Summer();

Sub.prototype.getSubName = function (){
    return this.SubNmae;
}

var SS = new Sub();
console.log(SS.getSubName());  //输出SubNmae
console.log(SS.getSummerName()); //输出Sum

</script>
<script>
function Summer() {
    this.SummerName = 'Sum';
}

Summer.prototype= function(){
    return this.SummerName;
}

function Sub () {
    this.SubNmae='SubNmae';
}

Sub.prototype = new Summer();

Sub.prototype = function (){
    return this.SubNmae;
}

var SS = new Sub();
console.log(SS);  //返回对象

</script>

构造函数继承

<script>
var person = {
    name: '张三',
};


var name = 'window';


var getName = function(){
    console.log(this.name);
}


getName() // 输出window
getName.call(person) // 输出张三
</script>
<script>
function person(name) {
    this.name = name;
}
function username(name, age) {
    name = name;
    person.call(this, name);
    this.age = age;
}


var ch = new username('张三', 28);
console.log(ch.name);  //输出张三
console.log(ch.age);	//输出28
</script>

<script>
class Person{   //创建类
    constructor(name,age){
        this.name=name
        this.age=age
    }
}
var ch=new Person('张三',18)
console.log(ch);

</script>
<script>
//类的继承  extends 关键字左边是子类,右边是父类
class Father{
    constructor(name){
        this.name='father'
    }
    speak(){
        console.log('我是父类');
    }
}
class Son extends Father{

}
var son=new Son()
console.log(son.name);
son.speak()
</script>
<script>

class Father{
    constructor(name){
        this.name='father'
    }
    speak(){
        console.log('我是父类');
    }
}
class Son extends Father{
	say(){
		console.log('我是子类');  
	}
}
var son=new Son()
console.log(son.name);
son.speak()	//继承父类的
son.say()  //子类自己的
</script>
<script>
//构造函数的继承
//子类会自动继承父类的构造函数
//如果父类中没有声明构造函数,也会有一个默认的无参构造函数,这个函数子类也会继承
//如果父类中有声明了构造函数,子类中也声明了构造函数,则在子类的构造函数中编写代码之前,一定要使用super关键字调用父类的构造方法
class Father{
    constructor(name){
        this.name=name
    }
    speak(){
        console.log('我是父类');
    }
}
class Son extends Father{
	constructor(name,age) {
	    super(name)
		this.age=age
	}
	say(){
		console.log('我是子类');
	}
}
var son=new Son('张三',23)
console.log(son.name,son.age);
</script>
<script>
//继承中,如果子类和父类有相同名的方法,则会使用自己的,而不使用父类中的
class Father{
    constructor(name){
        this.name=name
    }
    say(){
        console.log('我是父类');
    }
}
class Son extends Father{
	constructor(name,age) {
		    super(name)
			this.age=age
		}
	say(){
		console.log('我是子类');
	}
}
var son=new Son()
son.say()  //输出我是子类
</script>

call方法

  • call 可以调用函数
  • call 可以修改this的指向,使用call()的时候 参数一是修改后的this指向,参数2,参数3…使用逗号隔开连接
<script>
function f1(){
    console.log('输出了');
}
f1.call()
</script>
<script>
function f1() {
    console.log(this); // this指window 在call调用函数后指向变化为Person
}
function Person() {
    this.name = name;
}
var per = new Person();
f1.call(per);
</script>
<script>
	//子类构造函数继承父类构造函数中的属性
function Parent(name,age){
    console.log(this);
    this.name=name
    this.age=age
}
function Chinese(name,age,sex){
    Parent.call(this,name,age)
    this.sex=sex
}
new Parent('张三',23)
new Chinese('李四',25,'男')
</script>

数组方法forEach遍历数组

<script>
var arr=[5,6,7,8]
 arr.forEach(function(value, index, arr) {
      console.log(value)
 })

</script>

数组方法filter过滤数组

<script>
var arr = [5, 6, 7, 8, 9, 10];
var news = arr.filter(function(value, index,arr) {
      
   return value >= 8;
});
console.log(news);  //[8,9,10]
</script>

数组方法some

<script>
var arr = [10, 20, 30];
 var news = arr.some(function(value,index,arr) {
     return value < 9;
  });
console.log(news);//返回值是false,只要查到一个满足条件的就终止循环了
</script>
<script>
var arr = [10, 20, 30];
 var news = arr.some(function(value,index,arr) {
     return value > 20;
  });
console.log(news);//返回值是true
</script>

trim方法去除字符串两端的空格

var a = '   hello   ';
console.log(a.trim())  //hello 去除两端空格
var b = '   w o r l d   ';
console.log(b.trim())  //w o r l d  去除两端空格

获取对象的属性名

<script>
 var person = {
     name: '张三',
     age: 19,
     sex: '男'
};
var result = Object.keys(person)
console.log(result)//[name,age,sex]
</script>

商品筛选案例

var tbody = document.querySelector('tbody') //获取页面tbody
//先定义数组对象
var data = [{
	id: 1,
	pname: '小米10',
	price: 5999
}, {
	id: 2,
	pname: 'oppoReno4',
	price: 2999
}, {
	id: 3,
	pname: '荣耀30s',
	price: 3299
}, {
	id: 4,
	pname: '华为畅享10s',
	price: 1999
}, {
	id: 5,
	pname: '华为mate40',
	price: 5999
},{
	id: 6,
	pname: '华为P40',
	price: 3999
}, {
	id: 7,
	pname: '金立',
	price: 999
},  ];
//forEach 循环data数组对象,赋值给tbody
data.forEach(function(value) {
	var tr = document.createElement('tr');  //动态创建tr
	tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';  //给tr赋值
	tbody.appendChild(tr); //将tr添加到tbody中
});
var btn = document.querySelector('button')  //获取button按钮
btn.addEventListener('click', function() {  //添加监听事件
	var f_price = document.querySelector('.f_price').value  //获取输入最低价格
	var l_price = document.querySelector('.l_price').value	//获取输入最高价格
	var phone = document.querySelector('.phone').value  //获取输入的品牌名
	tbody.innerHTML = '' //将tbody内容清空
	data.forEach(function(value) {   //forEach 循环data数组对象
		if (value.price < l_price && value.price > f_price) {  //添加判断条件

			var tr = document.createElement('tr');  //动态创建tr节点
			tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';  //动态添加内容
			tbody.appendChild(tr);  //将内容添加到页面tbody中
		}
		if (f_price == '' && l_price == '') {  //如果价格没输入则走这个语句,上面不执行
			if (value.pname.indexOf(phone) >= 0) { //模糊查询次数,如果查到有符合的则执行

				var tr = document.createElement('tr');	//动态创建tr节点
				tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';  //动态添加内容
				tbody.appendChild(tr);  //将内容添加到页面tbody中
			}
		}
	});
})

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

David凉宸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值