理解对象
对象
定义
有属性property
和方法function
就是对象。
解析
属性property
:描述对象的状态
方法function
:操作对象的属性-->改变对象的状态
对象 人类{
姓名:memo
身高:165cm
体重:60kg
}
方法
改名
长高
运动
从这个意义上来说,对象是一个容器,封装了一些属性和方法。
面向对象编程
定义
OOPObject-oriented programming
是一种编程方式
特点
继承性:子类自动继承其父级类中的属性和方法,并可以添加新的属性和方法或者对部分属性和方法进行重写。继承增加了代码的可重用性。
多态性:子类继承了来自父级类中的属性和方法,并对其中部分方法进行重写。
封装性:将一个类的使用和实现分开,只保留部分接口和方法与外部联系。
类 & 对象
基于类(例如JAVA C++)的编程语言:
对象object
依靠 类class
来产生。
解析
类class
:把对象的功能和方法
抽象成一个模板,是虚拟的。
对象object
:把虚拟的 类
具化成一个实例,是存在的。
原型 & 对象
基于原型(例如 JS)的编程语言:
对象object
利用 原型prototype
构造出来的。
解析
原型:是一个对象,其他对象可以通过它实现继承。
原型有个属性prototype = constructor:原型 实例的构造器指向原型本身 Method 原型的各种方法 __proto__ 实例的原型链 追溯 实例来源 constructor 显示构造器,追溯 这个原型的来源 prototype = constructor:原型的原型 原型的构造器指向 原型的原型 Method 原型的原型 的各种方法 __proto__ 原型的原型链,追溯原型的来源 ▼ 总结:原型的 prototype属性 = 构造实例的属性 + 存储可用的方法
原型链:如上所示↑
调用对象一个实例
的方法时,先从自身开始查找
如果没有就从原型上查找,找到了就可以使用
如果没有就从原型的原型查找…直到找不到返回null
像这样顺着原型一层一层查找的行为就是原型链。
▼ 总结:原型链 = __proto__.__proto__.__proto__...null
创建对象
JS中没有类
这种模板,如何创建对象?
使用构造函数作为对象的模板。
构造函数
作用:
这个函数的目的,就是操作一个新生的空对象,将其“构造”为需要的样子。
特点:
函数体内部使用了this关键字,代表了所要生成的对象实例。
生成对象的时候,必需用new命令,调用这个函数。
形式:
function Car(name,color,status){
this.name = name;
this.color = color; => 构造函数:构造this的属性,把参数赋给属性
this.status = status;
}
Car.prototype.run = function(){
console.log('running');
};
Car.prototype.stop = function(){ => 给构造函数的prototype属性上添加方法
console.log('stop');
};
Car.prototype.getStatus = function(){
console.log(this.status);
};
var Benz = new Car('Benz','black',30); => 使用new命令 生成一个实例,赋给Benz
Benz.run();//running
Benz.stop();//stop
Benz.getStatus();//30
var Audi = new Car('Audi','red',20)
*分析
Car是一个构造函数,用来构造实例Benz;(Car是个概念,Benz是个实物)
name,color,status 是Car的属性;(描述Car的状态,生来既有)
run,stop,getStatus 是Car的方法;(改变Car的状态,后来添加)
Benz 是这个构造函数所生成的实例,继承了Car的属性和方法。
*关系----------------------------------------——————--
构造函数
Car
属性 name,color,status => 用来构造 Benz
prototype Constructor:Car => 指向自身 (本构造器是Car)
原型链 __proto__
Constructor 指向Object(Car的构造器是Object)
Object方法
实例1
Benz
原型Car => 显示构造器,说明Benz是由Car创造的
属性1:属性值
属性2:属性值 => 继承Car属性 :传入的参数作为值
属性3:属性值
__proto__ => Car的 prototype
constructor:Car => 指向构造器Car本身
Method1
Method2 => Car的方法
Method3
__proto__
constructor:Object => 指向Car的 构造器Object
Method => Object的方法
Null
实例2
Audi
同上
*new——————————————————————————————————————————
new做了什么:
创建一个空对象,作为Benz
将Benz.__proto__指向Car.prototype
将Benz赋值给函数内部的this关键字
传入参数,调用Car,返回实例Benz。
new的作用:
如果不写new,这只是一个普通函数,相当于给函数Car又起了一个新名字,它返回undefined。
如果写了new,它就变成了一个构造函数,它绑定的this指向新创建的对象,并默认返回this。
*this——————————————————————————————————————————
this 是什么
执行上下文环境
this 怎么改
.call() & .apply()
*Demo——————————————————————————————————————————
1 人类有身高,体重,性别;会吃饭,跑步,学习。
2 有个人叫小明,
3 他的 身高180cm,体重65kg,性别男;
4 他当然也会吃饭,跑步,学习;而且拥有一个新技能:写代码。
5 小明有个儿子叫小小明;
6 他会吃饭,跑步,学习,写代码。因为爸爸是个程序员。
-------------------------------------------------------------------------------
0 人类是抽象了小明的一个概念,是虚拟的;小明是一个实体化的人类,现实存在的。
1 身高,体重,性别,是人类的属性,描述了人是什么状态;
吃饭,跑步,学习,是人类的方法,可以用这些方法改变人的一些状态。
2 var XiaoMing = new People => 初始化一个人类代号小明,把人的属性赋给小明。
3 他 = this 指代小明,数据180cm...是传入的参数,是小明的属性值,
所以他的身高180cm => this.height = 180cm 。
4 小明继承了人类的方法,这些方法所有人都可以用;写代码是小明独有的技能,其他人不可以用;
所以不能在小明的原型(xiaoMing.__proto__)=>人类(People.prototype)上添加。
需要使用Object.create()进行差异化继承。
5 小小明由小明而来,小明由人类而来,所以小小明一共继承了4个方法 。
判断谁从哪来,使用 instanceOf;判断方法从哪来,使用 hasOwnProperty 。
6 根据上下文环境,他 指代小小明,所以此时 this => 由小明变为小小明。
在小小明的语境里使用小明,不能用this指代,可以取个新代词 var father = xiaoming.
应用
1 构造函数:
创建一个 GoTop 对象 Demo
需求
new 一个 GotTop 对象则会在页面上创建一个回到顶部的元素,点击页面滚动到顶部。
属性
ct GoTop 对应的 DOM 元素的容器
target GoTop 对应的 DOM 元素
方法
bindEvent 用于绑定事件
createNode 用于在容器内创建节点
函数
function GotTop(ct,target){
this.ct = ;
this.target = ;
}
GotTop.prototype.createNode = function(){
};
GotTop.prototype.bindEvent = function(){
};
2 this
2.1 this
被动态修改的3种方法
.call() & .apply()
前提
函数在执行的时候,传入的参数默认为( this,arguments )
*相同
传入的第一个参数是this,之后的参数为arguments
*区别
.call的arguments是列表 => .call( Obj, a1, a2, a3, a4, a5 ) ↘ 两种写法
.apply的arguments是数组 => .apply(Obj, [a1, a2, a3, a4, a5]) ↗ 等价
*不修改this
第一个参数为null
*Demo
var john = {
firstName: "John"
}
function func() { => this = window
alert( this.firstName )
}
func.call(john) //alert(John) => this = john
*其他用法
1 Math.max.apply(null, Array) =>返回数组中最大的元素
2 Array.prototype.slice.apply(arguments)
作用:把类数组对象转化为真正的数组
注意:类数组对象是这种形式=> arguments={key:number,length:n}
3 Array.apply(null, ["a",,"b"]) =>把空对象转化为undefined
作用:把空对象转化为undefined
注意:使用forEach遍历数组的时候,会跳过空对象,不会跳过undefined
.bind()
?????????????????
2.2 this
根据函数执行环境改变的4种方式
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func ■ 属于 方法调用模式,this => 调用方
john.sayHi() //alert(John: hi!)
var func= function(){
alert(this.firstName + ": hi!")
} ■ 属于 函数调用模式,this => window
func('john') // alert(undefined: hi!)
function func() {
this.firstName + ": hi!"
} ■ 属于 构造函数调用模式,this=>新创建的对象
new func()// 返回一个新对象
.call() & .apply() ■ 属于 动态修改调用模式,this => 传入的第一个参数
2.3 this
在setTimeout
/ setInterval
方法中
document.addEventListener('click', function(e){
console.log(this); => this = document
在事件处理程序中this代表事件源DOM对象
setTimeout(function(){
console.log(this); => this = window
setTimeout/setInterval执行的函数this是全局对象
}, 200);
}, false);
2.4 this
的储存
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this)
this.showMsg(); => this = $btn
})
},
showMsg: function(){ => showMsg这个方法绑在$btn上
console.log('饥人谷'); 无法通过调用module获得
}
}
修改-------------------------------------------------------------
var module= {
bind: function(){
var mod = this; => 给此时this指代的module换个名字
$btn.on('click',function(){
console.log(this); => 代码运行到这里,this指向$btn
mod.showMsg(); => showMsg方法仍然绑定在module上
})
},
showMsg:function(){
console.log('jirengu');
}
}
3 原型
3.1 扩展String
需求
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
实现
String.prototype.getMostOften = function(){
var obj = {};
for(var i=0; i<this.length; i++){
var k = this[i];
if(obj[k]){
obj[k]++;
}else{
obj[k] = 1;
}
}
console.log(obj); // Object {a: 1, h: 1, b: 2, c: 2, d: 5…}
var num = 0;
var word = '';
for(var key in obj){
if(obj[key] > num){
num = obj[key];
word = key;
}
}
return word + ',因为' + word + ' 出现了' + num + '次'
}
3.2 instanceOf
*作用
判断一个对象是否为另一个对象的实例
*Demo
function instanceOf(obj,fn){
var oldpro = obj.__proto__;
while(oldpro){
if(oldpro === fn.prototype){ => 如果obj.__proto__ 指向 fn.prototype
return true; 则 obj 是 fn 的实例
}else{
oldpro = oldpro.__proto__;
}
}
return false;
}
4 继承
*定义
继承是指一个对象直接使用另一个对象的属性和方法。
*作用
继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化;
继承是实现代码复用、扩展软件功能的重要手段,
完全相同的属性和方法不必重写,只需写出新增或改写的内容。
4.1 继承的复用性
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){ => 方法作为属性储存在构造器里
console.log(this.name);
}
}
var p1 = new People('饥人谷', 2) => 新建一个对象就重新生成一次printName
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){ => 方法储存在__prootype__里,
console.log(this.name); 使用时只要顺着原型链查找即可
}
var p1 = new Person('若愚', 27); 优点:节省内存
4.2 继承的新增
*方法 Object.create
*作用 创建一个拥有指定原型和若干个指定属性的对象
*Demo
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
console.log(this.name);
} ------------------------------------------- 构造函数Person
function Male(name, age, sex){
Person.call(this, name, age); => 初始化Person,使Male实现继承
this.sex = sex;
} ------------------------------------------- 复制Person的属性
方法1 使用场景:不兼容Object.create()
Male.prototype = new Person(); ---------
丨--- 使Male的原型指向Person
方法2 使用场景 :兼容Object.create() ----
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male; ---------- 把Male的原型构造器改为male
Male.prototype.sayAge = function(){---------- 给Male的原型绑定方法
console.log(this.age);
};
var p1 = new Male('hunger', 20, 'nan');------ 实例化Male
p1.sayName();//hunger
p1.sayAge();//20
4.3 继承的层次性
*方法 .hasOwnProperty()
*作用 判断一个对象是否包含自定义属性而不是原型链上的属性;
是JavaScript中唯一 处理属性但是不查找原型链的函数。
*Demo
p1.hasOwnProperty('name');//true
p1.hasOwnProperty('sayName');//false
Male.prototype.hasOwnProperty('sayAge');//true
网友评论