1.面向对象
- 在js中,有2种编程思维
- 面向过程:
- 面向对象:
- 核心就是对象(类),对象的组成有2种 {“name”:ls, skill:function(){console.log(“敲代码”)} }
- 属性:描述 静态的
- 方法:行为 动态的
- 面向对象三大特点
- 封装
- 继承
- 多态
1.1创建面向对象
1.1.1字面量创建
缺点:创建单个
var obj = {
"name": "zs",
"age": 23,
"skill": function () {
console.log("敲代码")
}
}
console.log(obj);
console.log(obj.age);//23
obj.skill(); //敲代码
</script>
2.1.1new关键字创建
缺点:代码冗余
<script>
// 创建张三的对象
// 1.创建空对象
var obj = new Object();
console.log(obj);//{}
// 2.添加属性和方法
obj.name = "李四";
obj.age = 20;
obj.skill = function(){
console.log("敲代码")
}
console.log(obj);
obj.skill();
</script>
2.1.2工厂模式创建
缺点:类别识别不明确,代码冗余 浪费内存
<script>
function createObj(name,age){ // name 张三 age 20
//1.创建空对象
var obj = new Object();
//2.添加属性和方法
obj.name = name;
obj.age = age;
obj.skill = function(){
console.log("敲代码")
}
// 3.出厂 设置返回值
return obj;
}
var res1 = createObj("张三",20);
console.log(res1);
var res2 = createObj("李四",20);
console.log(res2);
</script>
2.1.3构造函数创建
缺点:浪费内存
如何创建构造函数
- 构造函数的函数名首字母必须大写,为了和普通函数做区别
- 方法和属性是直接给this
- 必须使用new关键字进行调用 否则和普通函数没有区别
new操作符做了什么
- 隐式创建了一个空对象,让this指向这个空对象
- 执行构造函数中的代码
- 将实例化对象的__ proto __ 指向构造函数的prototype
- 隐式返回对象
<script>
// 创建构造函数
function Person(name, age) {
//new关键字 隐式创建了一个空对象 让this指向这个空对象
//添加属性和方法 必须加给this
this.name = name,
this.age = age,
this.skill = function () {
console.log("敲代码")
}
// new关键字 隐式返回这个对象
}
// 实例化对象(调用构造函数) 必须使用new关键字
var res1 = new Person("张三", 20);
console.log(res1);
var res2 = new Person("李四",10);
</script>
2.1.4原型创建
缺点:不能传参
//创造构造函数
function Person(){}
// 将方法和属性添加到构造函数的prototype上 共享的属性和方法
console.dir(Person);
Person.prototype.name = "张三";
Person.prototype.age = 20;
Person.prototype.skill = function(){
console.log("敲代码")
}
console.dir(Person);
// 实例化对象
var res1 = new Person();
console.log(res1);//实例化对象的__proto__指向构造函数的prototype
console.log(res1.__proto__);
var res2 = new Person();
console.log(res2);
console.log(res2.__proto__);
2.1.5混合创建
构造函数创建(传参)+原型创建(不传参)
<script>
/* name age传参 skill不传参 */
// 创建Student构造函数
function Student(name, age) {
this.name = name
this.age = age
}
// 原型创建 prototype
Student.prototype.skill = function () {
console.log("学习敲代码")
}
// 实例化对象
var res1 = new Student("张三", 20);
console.log(res1);
var res2 = new Student("李四", 15);
console.log(res2);
console.log(res1.name);//张三
res.skill();//学习敲代码
res.skill1();//
</script>
2.2什么是原型和原型链
- 原型prototype:构造函数中用来存储共享的方法和属性的对象
- 原型属性 __ proto __ :让实例化对象的 proto__指向构造函数的prototype
// Array是js内部创建好的构造函数
console.dir(Array);
// 实例化对象 实例化对象的__proto__指向构造函数的prototype
var arr = new Array(1,2,3,4,5);
console.log(arr);
console.log(Array.prototype === arr.__proto__);//true
console.dir(Array.prototype);//Array上共享的属性和方法
var arr = new Array(1,2,3,4,5); //arr的__proto__ 指向Array的prototype
var arr1 = new Array(4,5,6,6);// arr1的__proto__指向Array的prototype
-
原型链:在创建构造函数和实例化对象的时候 自动形成一种查找关系
先查找自身的属性和方法 然后再找__proto__,再找构造函数 如果都找不到返回undefined
2.3this的指向
1.this的指向问题
- 在事件处理函数中 this指向当前触发事件的对象(标签)
- 在Object数据类型中的方法中 this指向所在方法的对象
- 在普通函数中 this指向window
- 在构造函数中 this指向实例化对象
<script>
// 1.在事件处理函数中 this指向当前触发事件的对象(标签)
var btn1 = document.getElementById("btn1");
btn1.onclick = function(){
console.log(this);//
}
// 2.在Object数据类型中的方法中 this指向所在方法的对象
var obj = {
"name":"zs",
"eat":function(){
console.log(this);//obj
}
}
obj.eat();
// 3.在普通函数中 this指向window
function fun1(){
console.log(this);//window
}
fun1();
// 4.在构造函数中 this指向实例化对象
function Person(name){
this.name = name,
this.skill = function(){
console.log(this);//实例化对象
}
}
var res = new Person("ls");
res.skill();
</script>
2.如何改变this指向
- call(this的新指向,参数1,参数2…) 参数是分开写的 用逗号分隔
- apply(this的新指向,[参数1,参数2…])
var obj = {
"name": "小红",
"age": 10,
"getName": function () {
console.log(this.name);
}
}
obj.getName();// 小红 this指向 obj
var obj1 = {
"name": "小明"
}
obj.getName.call(obj1);//this指向obj1 小明
function fun1() {
console.log(this)
}
fun1();//this指向window
fun1.call(document.documentElement);
fun1.call(1);//
fun1.call("123");//
function fun2(a, b) {
console.log(a, b, this);
}
fun2(100, 200);// 100 200 window
fun2.call(obj1, 100, 200);// 100 200 obj1:{name:"小明"}
// 详细检测数据类型
console.log(Object.prototype.toString.call("124"))
console.log(Object.prototype.toString.call(123))
console.log(Object.prototype.toString.call(true))
console.log(Object.prototype.toString.call(undefined))
console.log(Object.prototype.toString.call(null))
console.log(Object.prototype.toString.call({}))
console.log(Object.prototype.toString.call([]))
console.log(Object.prototype.toString.call(function () { }))
console.log(Object.prototype.toString.call(new Date()))
console.log(Object.prototype.toString.call(/\d/gi))
//instanceof 检测当前数据是否属于某个构造函数
function Person() {
this.name = "ls"
}
var res = new Person();
// 检测res是否由Person构造函数创建的
console.log(res instanceof Person);//true
// apply(this的新指向,[参数1,参数2......])
function fun3(a,b){
console.log(this,a,b)
}
fun3();//window
fun3.apply(obj1,[100,200]);// obj1 100 200
//利用Math.max和Math.min求数组中最大的值和最小的值
var arr = [100,80,120,60];
// Math.max(序列1,序列2.....)
var a = Math.max.apply("12344",arr);
console.log(a);
var a = Math.min.apply("123",arr);
console.log(a);
3.面向对象的选项卡
<script>
// var btn = document.getElementsByTagName("button");
// var odiv = document.getElementsByTagName("div");
// for(var i = 0;i<btn.length;i++){
// btn[i].index =i;
// btn[i].onclick = function(){
// for(var j = 0;j<odiv.length;j++){
// odiv[j].style.display = "none";
// }
// odiv[this.index].style.display = "block";
// }
// }
/*
面向对象的选项卡
创建面向对象构造函数 面向对象都是由属性和方法组成的
标签作为对象的属性 点击事件和for循环作为对象的方法
*/
function SwitchTab() {
// 添加属性
this.btn = document.getElementsByTagName("button");
this.odiv = document.getElementsByTagName("div");
var that = this;// 在这里this还是指向实例化对象的
// 入口方法 添加方法
this.init = function () {
for (var i = 0; i < this.btn.length; i++) {
this.btn[i].index = i;
this.btn[i].onclick = function () {
// console.log(this);//在事件处理函数中 this指向当前触发事件的对象
// 如何让this指向实例化对象
that.changeItem(this.index);//想让this指向实例化对象
}
}
}
// 入口方法调用
this.init();
this.changeItem = function (index) {
for (var j = 0; j < this.odiv.length; j++) {
this.odiv[j].style.display = "none";
}
// this.index 想让this指向触发对象 但是现在这个this指向实例化对象
this.odiv[index].style.display = "block";
}
}
// 实例化对象
new SwitchTab();
</script>