01 课程介绍
02 复习
JavaScript简称:JS
JS分三个部分:
1 ECMAScript标准—基础的语法
2 DOM Document Object Model 文档对象模型
3 BOM Browser Object Model 浏览器对象模型
什么是JS?
是一门脚本语言
是一门解释性语言
是一门弱类型语言
是一门基于对象的语言
是一门动态类型的语言
动态页面:页面由html+css+Js
向服务器发送请求,服务器那边没有页面,是动态的生成,返回给客户端
js最初的目的:解决用户和服务器之间的交互问题
js做特效,游戏,移动端,服务端
编程思想:
面向过程:所有的事情都是亲力亲为,注重的是过程
面向对象:提出需求,找对象,对象解决,注重的是结果
js不是一门面向对象的语言,是基于对象的语言,js来模拟面向对象
面向对象的特性:封装,继承,多态,(抽象性)
封装:就是包装,把一些重用的内容进行包装,在需要的时候,直接使用
把一个值,存放在一个变量中,把一些重用的代码放在函数中,把好多相同功能的函数放在一个对象中,把好多功能的对象,放在一个文件中,把一些相同的内容放在一个对象中
继承:类与类之间的关系,js中没有类的概念,js中有构造函数的概念,是可以有继承的,是基于原型
多态:同一个行为,针对不同的对象,产生了不同的效果
03创建对象的三种方式
对象:特指的某个事物,具有属性和方法(一组无序的属性的集合)
特征---->属性
行为---->方法
小苏:------>姓名,性别,年龄,吃,睡觉,玩
创建对象三种方式:
1 字面量的方式
2 调用系统的构造函数
3 自定义构造函数方式
实例对象
var per1={
name:"卡卡西",
age:20,
sex:"男",
eat:function () {
console.log("吃臭豆腐");
},
readBook:function () {
console.log("亲热天堂");
}
};
调用系统的构造函数
var per2=new Object();
per2.name="大蛇丸";
per2.age=30;
per2.sex="男";
per2.eat=function () {
console.log("吃榴莲");
};
per2.play=function () {
console.log("这个小蛇真好玩");
};
function Person() {
}
console.log(per2 instanceof Object);
var dog=new Object();
自定义构造函数
function Person(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
this.play=function () {
console.log("天天打游戏");
};
}
var per=new Person("雏田",18,"女");
console.log(per instanceof Person);
04 自定义构造函数创建对象做的事情
function Person(name,age) {
this.name=name;
this.age=age;
this.sayHi=function () {
console.log("您好");
};
}
创建对象---->实例化一个对象,的同时对属性进行初始化
var per=new Person("小红",20);
1.开辟空间存储对象
2.把this设置为当前的对象
3.设置属性和方法的值
4.把this对象返回
05 工厂模式创建对象
function createObject(name,age) {
var obj=new Object();
obj.name=name;
obj.age=age;
obj.sayHi=function () {
console.log("您好");
};
return obj;
}
function Person(name,age) {
this.name=name;
this.age=age;
this.sayHi=function () {
console.log("您好");
};
}
创建对象---->实例化一个对象的同时对属性进行初始化
共同点:都是函数,都可以创建对象,都可以传入参数
工厂模式:
函数名是小写
有new,
有返回值
new之后的对象是当前的对象
直接调用函数就可以创建对象
自定义构造函数:
函数名是大写(首字母)
没有new
没有返回值
this是当前的对象
通过new的方式来创建对象
06 构造函数和实例对象之间的关系
面向对象的思想是----抽象的过程---->实例化的过程
小苏这个人,姓名,年龄,性别, 吃饭,打招呼,睡觉
自定义构造函数----->实例化对象
function Person(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
this.eat=function () {
console.log("吃大蒜拌臭豆腐加榴莲酱");
};
}
构造函数---->创建对象
var per=new Person("小苏",38,"女");
per.eat();//吃
实例对象是通过构造函数来创建
实例对象会指向自己的构造函数(暂时理解,是错误的)
把这个对象的结构显示出来
console.dir(per);
console.dir(Person);
实例对象的构造器(构造函数)
实例对象的构造器是指向Person
的,结果是true
,所以,这个实例对象per
就是通过Person
来创建的
console.log(per.constructor==Person);//
console.log(per.__proto__.constructor==Person);
console.log(per.__proto__.constructor==Person.prototype.constructor);
构造函数
function Animal(name) {
this.name=name;
}
实例对象
var dog=new Animal("大黄");
console.dir(dog);//实例对象
console.dir(Animal);//构造函数的名字
console.log(dog.__proto__.constructor==Person);
console.log(dog.__proto__.constructor==Animal);
判断这个对象是不是这种数据类型
console.log(dog.constructor==Animal);
console.log(dog instanceof Person);
总结:
实例对象和构造函数之间的关系:
实例对象
是通过构造函数
来创建的—创建的过程叫实例化
2.如何判断对象是不是这个数据类型?
- 通过构造器的方式 实例对象.构造器==构造函数名字
- 对象 instanceof 构造函数名字
尽可能的使用第二种方式来识别,为什么?原型讲完再说
07 构造函数创建对象带来的问题
function Person(name,age) {
this.name=name;
this.age=age;
this.eat=function () {
console.log("今天吃红烧土豆");
}
}
var per1=new Person("小白",20);
var per2=new Person("小黑",30);
console.dir(per1);
console.dir(per2);
function myEat() {
console.log("吃大榴莲");
}
var myEat=10;
function Person(name,age) {
this.name=name;
this.age=age;
this.eat=myEat;
}
var per1=new Person("小白",20);
var per2=new Person("小黑",30);
console.dir(per1);
console.dir(per2);
console.log(per1.eat==per2.eat);
通过原型来解决---------数据共享,节省内存空间,作用之一
per1.eat();
per2.eat();
//不是同一个方法
console.log(per1.eat==per2.eat);
for(var i=0;i<100;i++){
var per=new Person("嘎嘎",20);
per.eat();
}
08 原型添加方法解决数据共享问题
function Person(name,age) {
this.name=name;
this.age=age;
}
通过原型来添加方法,解决数据共享,节省内存空间
Person.prototype.eat=function () {
console.log("吃凉菜");
};
var p1=new Person("小明",20);
var p2=new Person("小红",30);
console.log(p1.eat==p2.eat);//true
console.dir(p1);
console.dir(p2);
实例对象中根本没有eat方法,但是能够使用,这是为什么?
09 原型
function Person(name,age) {
this.name=name;
this.age=age;
}
//通过原型来添加方法,解决数据共享,节省内存空间
Person.prototype.eat=function () {
console.log("吃凉菜");
};
var p1=new Person("小明",20);
var p2=new Person("小红",30);
console.dir(p1);
console.dir(p2);
console.dir(Person);
p1.__proto__.eat();
console.log(p1.__proto__==Person.prototype);
原型?
- 实例对象中有__proto__这个属性,叫原型,也是一个对象,这个属性是给浏览器使用,不是标准的属性----->proto----->可以叫原型对象
- 构造函数中有prototype这个属性,叫原型,也是一个对象,这个属性是给程序员使用,是标准的属性------>prototype—>可以叫原型对象
- 实例对象的__proto__和构造函数中的prototype相等—>true
- 又因为实例对象是通过构造函数来创建的,构造函数中有原型对象prototype
- 实例对象的__proto__指向了构造函数的原型对象prototype
window是对象
document是属性,document也是一个对象
write()是方法
window.document.write(“哈哈”);
对象.style.color=值;
10 体会面向过程和面向对象的编程思想
<style>
div {
width: 300px;
height: 200px;
background-color: red;
}
</style>
<input type="button" value="显示效果" id="btn"/>
<div id="dv"></div>
<script src="common.js"></script>
function ChangeStyle(btnObj, dvObj, json) {
this.btnObj = btnObj;
this.dvObj = dvObj;
this.json = json;
}
ChangeStyle.prototype.init = function () {
//点击按钮,改变div多个样式属性值
var that = this;
this.btnObj.onclick = function () {//按钮
for (var key in that.json) {
that.dvObj.style[key] = that.json[key];
}
};
};
实例化对象
var json = {"width": "500px", "height": "800px", "backgroundColor": "blue", "opacity": "0.2"};
var cs = new ChangeStyle(my$("btn"), my$("dv"), json);
cs.init();//调用方法
点击p标签,设置div的样式
点击按钮,改变div的背景颜色
document.getElementById("btn").onclick=function () {
document.getElementById("dv").style.backgroundColor="yellow";
};
面向对象思想----初级的
按钮是一个对象,div是一个对象,颜色是一个属性
function ChangeStyle(btnId,dvId,color) {
this.btnObj=document.getElementById(btnId);//按钮对象
this.dvObj=document.getElementById(dvId);//div对象
this.color=color;//颜色
}
//数据共享来改变背景颜色
ChangeStyle.prototype.init=function () {
console.log(this);//就是实例对象---就是当前对象
var that=this;
//点击按钮,改变div的背景颜色
this.btnObj.onclick=function () {
that.dvObj.style.backgroundColor=that.color;
};
};
实例化对象
var cs=new ChangeStyle("btn","dv","yellow");
cs.init();
function Person() {
this.sayHi=function () {
console.log(this);
};
}
var p=new Person();
p.sayHi();
11 复习原型
构造函数
function Person(sex,age) {
this.sex=sex;
this.age=age;
}
通过原型添加方法
Person.prototype.sayHi=function () {
console.log("打招呼,您好");
};
var per=new Person("男",20);
console.log(per.__proto__.constructor==Person.prototype.constructor);//实例对象
console.dir(Person);//构造函数的名字
var per2=new Person("女",30);
console.log(per.sayHi==per2.sayHi);
实例对象中有两个属性(这两个属性是通过构造函数来获取的),__proto__这个属性
构造函数中并没有sex和age的两个属性
实例对象中有个属性,proto,也是对象,叫原型,不是标准的属性,浏览器使用的
构造函数中有一个属性,prototype,也是对象,叫原型,是标准属性,程序员使用
原型---->__proto__或者是prototype,都是原型对象,
原型的作用:共享数据,节省内存空间
12 构造函数和实例对象和原型对象之间的关系
通过构造函数实例对象,并初始化
var arr=new Array(10,20,30,40);
join是方法,实例对象调用的方法
arr.join("|");
console.dir(arr);
join方法在实例对象__proto__原型
console.log(arr.__proto__==Array.prototype);
原型的作用之一:共享数据,节省内存空间
构造函数
function Person(age,sex) {
this.age=age;
this.sex=sex;
}
通过构造函数的原型添加一个方法
Person.prototype.eat=function () {
console.log("明天中午吃完饭就要演讲,好痛苦");
};
var per=new Person(20,"男");
// per.__proto__.eat();
per.eat();
// per.eat();
13 总结三者之间的关系
- 构造函数可以实例化对象
- 构造函数中有一个属性叫prototype,是构造函数的原型对象
- 构造函数的原型对象(prototype)中有一个constructor构造器,这个构造器指向的就是自己所在的原型对象所在的构造函数
- 实例对象的原型对象(proto)指向的是该构造函数的原型对象
- 构造函数的原型对象(prototype)中的方法是可以被实例对象直接访问的
14 利用原型共享数据
什么样子的数据是需要写在原型中?
需要共享的数据就可以写原型中
原型的作用之一:数据共享
- 属性需要共享,方法也需要共享
- 不需要共享的数据写在构造函数中,需要共享的数据写在原型中
构造函数
function Student(name,age,sex) {
this.name=name;
this.age=age;
this.sex=sex;
}
- 所有学生的身高都是188,所有人的体重都是55
- 所有学生都要每天写500行代码
- 所有学生每天都要吃一个10斤的西瓜
原型对象
Student.prototype.height="188";
Student.prototype.weight="55kg";
Student.prototype.study=function () {
console.log("学习,写500行代码,小菜一碟");
};
Student.prototype.eat=function () {
console.log("吃一个10斤的西瓜");
};
实例化对象,并初始化
var stu=new Student("晨光",57,"女");
console.dir(Student);
console.dir(stu);
stu.eat();
stu.study();
15 原型的简单的语法
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
简单的原型写法
Student.prototype = {
//手动修改构造器的指向
constructor:Student,
height: "188",
weight: "55kg",
study: function () {
console.log("学习好开心啊");
},
eat: function () {
console.log("我要吃好吃的");
}
};
var stu=new Student("段飞",20,"男");
stu.eat();
stu.study();
console.dir(Student);
console.dir(stu);
Student.prototype.height="188";
Student.prototype.weight="55kg";
Student.prototype.study=function () {
console.log("学习,写500行代码,小菜一碟");
};
Student.prototype.eat=function () {
console.log("吃一个10斤的西瓜");
};
//实例化对象,并初始化
var stu=new Student("晨光",57,"女");
console.dir(Student);
console.dir(stu);
16 原型中的方法是可以相互访问的
function Person(age) {
this.age=age;
this.sayHi=function () {
console.log("考尼奇瓦");
//打招呼的同时,直接调用吃的方法
};
this.eat=function () {
console.log("吃东西啦");
this.sayHi();
};
}
实例对象的方法,是可以相互调用的
实例化对象,并初始化
var per=new Person(20);
//调用方法
per.sayHi();
per.eat();
原型中的方法,是可以相互访问的
function Animal(name,age) {
this.name=name;
this.age=age;
}
原型中添加方法
Animal.prototype.eat=function () {
console.log("动物吃东西");
this.play();
};
Animal.prototype.play=function () {
console.log("玩球");
this.sleep();
};
Animal.prototype.sleep=function () {
console.log("睡觉了");
};
var dog=new Animal("小苏",20);
dog.eat();
原型对象中的方法,可以相互调用
17 实例对象使用属性和方法层层的搜索
function Person(age,sex) {
this.age=age;//年龄
this.sex=sex;
this.eat=function () {
console.log("构造函数中的吃");
};
}
Person.prototype.sex="女";
Person.prototype.eat=function () {
console.log("原型对象中的吃");
};
var per=new Person(20,"男");
console.log(per.sex);//男
per.eat();
console.dir(per);
实例对象使用的属性或者方法,先在实例
中查找,找到了则直接使用,找不到则,去实例对象的__proto__
指向的原型对象prototype
中找,找到了则使用,找不到则报错
18 为内置对象添加原型方法
为内置对象添加原型方法
var arr=new Array(10,20,30,40,50);
arr.join("|");
console.dir(arr);
var str=new String("哦,唛嘎的");
str.indexOf("哦");
console.dir(str);
var dt=new Date();
dt.getFullYear();
console.dir(dt);
实例中的方法如果没有,去创建该实例对象的构造函数的原型对象中找
我们能否为系统的对象的原型中添加方法,相当于在改变源码
我希望字符串中有一个倒序字符串的方法
String.prototype.myReverse=function () {
for(var i=this.length-1;i>=0;i--){
console.log(this[i]);
}
};
var str="abcdefg";
str.myReverse();
为Array内置对象的原型对象中添加方法
Array.prototype.mySort=function () {
for(var i=0;i<this.length-1;i++){
for(var j=0;j<this.length-1-i;j++){
if(this[j]<this[j+1]){
var temp=this[j];
this[j]=this[j+1];
this[j+1]=temp;
}//end if
}// end for
}//end for
};
var arr=[100,3,56,78,23,10];
arr.mySort();
console.log(arr);
String.prototype.sayHi=function () {
console.log(this+"哈哈,我又变帅了");
};
字符串就有了打招呼的方法
var str2="小杨";
str2.sayHi();
函数的自调用—自调用函数
一次性的函数–声明的同时,直接调用了
(function () {
console.log("函数");
})();
页面加载后.这个自调用函数的代码就执行完了
(function (形参) {
var num=10;//局部变量
})(实参);
console.log(num);
(function (win) {
var num=10;//局部变量
//js是一门动态类型的语言,对象没有属性,点了就有了
win.num=num;
})(window);
console.log(num);
如何把局部变量变成全局变量?
把局部变量给window就可以了
20 把随机数对象暴露给window成为全局对象
通过自调用函数产生一个随机数对象,在自调用函数外面,调用该随机数对象方法产生随机数
(function (window) {
//产生随机数的构造函数
function Random() {
}
//在原型对象中添加方法
Random.prototype.getRandom = function (min,max) {
return Math.floor(Math.random()*(max-min)+min);
};
//把Random对象暴露给顶级对象window--->外部可以直接使用这个对象
window.Random=Random;
})(window);
//实例化随机数对象
var rm=new Random();
//调用方法产生随机数
console.log(rm.getRandom(0,5));
其他参考链接
【js高级 Day1】深入理解原型及作用,构造函数和实例对象和原型对象之间的关系
【js高级 Day2】深入理解原型添加方法,私有函数,面向对象的编程思想(案例小贪吃蛇)
【js高级 Day3】深入理解原型的方式继承,借用构造函数继承,组合继承,拷贝继承
【js高级 Day4】深入理解apply和call方法,作用域,闭包,递归
【js高级 Day5】深入理解浅拷贝,深拷贝,遍历DOM树,正则表达式
【如果你是新手】推荐链接
【 js基础 Day2】js的流程控制:分支语句,循环.顺序结构
【 js基础 Day3】关键字的使用,数组(重点)和函数(重点)
【 js基础 Day4】面向过程,面向对象,自定义对象,内置对象