基本的面向对象
- 拥有自己的属性
- 拥有自己的方法
- 数值,字符,布尔,对象, undefined
- 数组, array
基本面向对象的写法
var dog = {
name:'小花',
age:1,
friendDogs:['小黄','小虎'],
eat:function(someThing){
console.log('吃' + someThing);
},
run:function(someWhere){
console.log('跑' + someWhere);
}
}
dog.eat('奶');
dog.run('树下');
面向对象的常用写法
function dog(){
var obj = new Object();
obj.name = '未定义';
obj.age = 0;
obj.eat = function(someThing){
console.log(this.name + '吃' + someThing)
};
obj.run = function(someWhere){
console.log(this.name + '跑' + someWhere);
}
run obj;
}
var smallDog = dog();
smallDog.name = '小花';
smallDog.age = 1;
smallDog.eat('奶');
var bigDog = dog();
bigDog.name = '大花';
bigDog.age = 1;
bigDog.run('棠下');
bigDog.eat('肉');
this 对象的认识
- this : this 所在的函数(方法)属于哪个对象,那么 this 就表示哪个对象
- this 在事件指令中表示事件源
- window.所有的全局变量都是它的属性,所有的全局的函数都是它的方法
- this 在定时器表示 window
- 任何一个函数都可以通过 New+ 函数调用创建一个对应的对象
- 如果遇到 new 函数调用会创建一个新的对象,那么这个函数就属于新创建的对象,所以 this 表示这个对象
通过构造函数创建对象
- 构造函数
形式:第一个字母都是大写
new: 可以创建一个对象返回来
创建对象,使用构造函数
function Dog(name,age,dogFriends){
this.name = name;
this.age = age;
this.dogFriends = dogFriends;
this.eat = function(someThing){
console.log(this.name + '吃' + someThing);
}
this.run = function(someWhere){
console.log(this.name + '跑' + someWhere);
}
}
//通过构造函数创建对象
var smallDog = new Dog('小花',1,['小虎','小明']);
smallDog.eat('奶');
smallDog.run('教室');
var bigDog = new Dog('大花',1,['大虎','大明']);
bigDog.eat('肉');
bigDog.run('树下');
通过构造函数创建对象优化
//创建对象,使用构造函数
//优化:就是使用json把参数保存起来,直接传递json
function Dog(option) {
var option = option ||{};
this.name = option.name;
this.age = option.age;
this.dogFridends = option.dogFridends;
this.eat = function (someThing) {
console.log(this.name +'吃' + someThing);
}
this.run = function (someWhere) {
console.log(this.name +'跑'+someWhere);
}
}
//2.通过构造函数创建对象
var smallDog = new Dog({name:'小花',age:1,dogFriends:['小虎','小明']});
console.log(smallDog.name);
console.log(smallDog.age);
smallDog.eat('奶');
smallDog.run('教室');
var bigDog = new Dog({name:'大花',age:8,dogFriends:['大虎','大明']});
console.log(bigDog.name);
console.log(bigDog.age);
bigDog.eat('肉');
bigDog.run('棠下');
- 当我们使用不同的对象调用函数的时候,这个函数不是同一个函数
- 每次创建对象,调用函数的时候,这个函数都需要重新创建
- 但是这两个函数功能是一样的,我们每必要每次创建一个对象都使用新的函数
- 所以我们需要这个 eat 函数可以共用,无论哪个对象调用,都是同一个函数
原型属性的使用
- 原型属性:可以扩展属性和方法,就是一个构造函数的共享库,以后所有创建的新的对象,都可以使用这个共享库中的方法以及属性
- 优点是降低了创建方法的成本
Array.prototype.eat = function(){
console.log('数组会吃东西');
};
Array.prototype.run = function(){
console.log('数组会跑');
};
//原型库的第二种写法
Dog.prototype = {
eat:function(someThing){
console.log(this.name +
'吃' +someThing);
},
run:function(someWhere){
console.log(this.name + '跑' +someWhere);
}
};
通过构造函数创建对象最终版
- 要把属性也放在原型库中,使用一个初始化方法 _init
- 在构造函数中调用初始化方法,然后把这个初始化方法放在原型库中,初始化方法用来初始化属性
function Dog(option){
this._init(option);
}
Dog.prototype = {
_init:funtion(option){
var option = option || {};
this.name = option.name;
this.age = option.age;
this.dogFriends = option.dogFriends;
},
eat:funtion(someThing){
console.log(this.name + '吃' + someThing);
}
}
ar smallDog = new Dog({name:'小花',age:1,dogFriends:['小虎','小明']});
console.log(smallDog.name);
console.log(smallDog.age);
smallDog.eat('奶');
smallDog.run('教室');
var bigDog = new Dog({name:'大花',age:8,dogFriends:['大虎','大明']});
console.log(bigDog.name);
console.log(bigDog.age);
bigDog.eat('肉');
bigDog.run('棠下');
面向对象创建一个矩形
/*1.创建一个构造函数用来创建矩形*/
function Rect(option){
this._init(option)
}
/*2.给rect设置原型对象*/
Rect.prototype = {
_init:function(option){
var option = option ||{};
/*2.1设置属性*/
/*2.11设置添加的父标签的id*/
this.parentId = option.parentId;
/*2.12设置宽度和高度*/
this.width = option.width||100;
this.height = option.height ||100;
/*2.13设置位置*/
this.left = option.left ||100;
this.top = option.top ||100;
/*2.14 设置其他属性*/
this.background = option.background ||'blue';
this.borderRadius = option.borderRadius ||10;
this.border = option.border ||0;
},
/*设置显示方法*/
render:function(){
/*1.创建一个父标签,用来添加我们的矩形*/
var parentNode = document.getElementById(this.parentId);
var childremNode = document.createElement('div');
parentNode.appendChild(childremNode);
/*2.设置子标签的样式*/
childremNode.style.position = 'absolute';
parentNode.style.position = 'relative';
childremNode.style.width = this.width +'px';
childremNode.style.height = this.height +'px';
childremNode.style.left = this.left +'px';
childremNode.style.top = this.top +'px';
childremNode.style.background = this.background;
childremNode.style.borderRadius = this.borderRadius +'px';
childremNode.style.border = this.border;
}
}
/*创建一个矩形*/
// this.width = option.width||100;
// this.height = option.height ||100;
// /*2.13设置位置*/
// this.left = option.left ||100;
// this.top = option.top ||100;
// /*2.14 设置其他属性*/
// this.background = option.background ||'blue';
// this.borderRadius = option.borderRadius ||10;
// this.border = option.border ||0;
var myRect = new Rect({parentId:'main',width:200,height:100,left:200,top:200,background:'red',borderRadius:10,border:'1px solid #ccc'});
alert(myRect);
/*渲染*/
myRect.render();
闭包的认识
- 如果访问一个局部变量,但是出了作用域就访问不到,我们想要访问这个变量需要使用闭包
- 闭包是在函数内部使用函数或者定义函数
- 闭包作用域链条:就是子对象可以访问对象所有的属性,反之不可以
就是访问变量的时候,会沿着作用域链条向上访问,不能反过来 - 闭包的优点是延长变量的使用周期,缺点是耗费性能
//第一步
function sum(){
var num = 10;
var result = function(){
console.log(num);
}
return result;
}
var result = sum();
//这样可以把变量通过返回函数的形式传递出来
//实际上内部函数可以匿名
function sun(){
var num = 10;
return function(){
console.log(num);
}
}
var result = sum();
console.log(num);
//第二种写法
sum()()
//这就是匿名函数传递参数
匿名函数自调
- 匿名函数自调内部可以继续使用匿名函数自调
- 当访问变量的时候,会先从自己的作用域访问对应的变量,如果没有,就沿着作用域链条向上访问,知道找到为止,如果没有返回未定义
- 为了提高性能一般不要多层嵌套匿名函数自调
- 为了提高性能一般不要使用全局变量
var num = 20;
(function(){
(function(){
console.log(num);
})()
})(num)
- 当使用全局变脸的时候,会把 window 中的所有的东西遍历一遍,直到找到对应的变量
for(var key in window){
}
访问变量的简单认识以及应用
//第一种写法,两次定义全局变量极其消耗性能,两次遍历 window
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn1');
//第二种写法,匿名函数的自调,只遍历一次 window 且是函数内部的局部变量
(function(){
var d = document;
var btn1 = d.getElementById('btn1');
var btn2 = d.getElementById('btn2');
})()
//第二种写法的变形,将document当作参数传递进去
(functiojn(document){
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn2');
})(document)
高级排他
var lis = document.getElementById('li');
//用来记录上一个移动到的位置
var lastIndex = 0;
for(var i = 0 ; i < lis.length;i++){
(function(index){
lis[i].onmouseover = function(){
lis[lastIndex].className = "";
this.className = 'curr';
lastIndex = index;
}
})(i)
}
使用闭包实现数据截流
function throtte(delay,fn){
var timer = null;
return function(){
clearTimerout(timer);
timer = setTimerout(fn,delay)
}
}
window.onresize = throtte(300,function(){
alert(0);
})