具体认识函数
具体认识对象
事件操作
ajax请求
JavaScript函数:
函数---就是某一个具体功能实现代码的集合
函数的创建
function 函数名称(参数列表){函数体}
函数安照有没有名称分为:有名函数和匿名函数
有名函数:function test1(){}
匿名函数:window.οnlοad=function(){}
函数安照有没有参数分为:无参数的函数和有参数的函数
参数---参数就是局部变量,接收函数之外的数据进入本函数中进行运算活动。
无参数的函数:function test1(){}
有参数的函数:function test2(num,str){}
函数安照有没有返回值分为:无返回值的函数和有返回值的函数
返回值---函数执行完成以后的最终的执行结果
无返回值的函数:function test1(){}
有返回值的函数:function test1(){ return xxxx;}
函数声明后不会立即执行,会在我们需要的时候调用到。
函数的调用:1.要什么,给什么
2.给什么,收什么
6.函数是对象
在 JavaScript 中使用 typeof 操作符判断函数类型将返回 "function" 。
function my1(a, b) {
return a * b;
}
alert(typeof my1);//function
但是JavaScript 函数描述为一个对象更加准确。
JavaScript 函数有 属性 和 方法。
arguments.length 属性返回函数调用过程接收到的参数个数.
function myFunction(a, b) {
return arguments.length;
}
toString() 方法将函数作为一个字符串返回.
function myFunction(a, b) {
return a * b;
}
var txt = myFunction.toString();
8.函数的调用
1.作为一个函数调用
function test1(num1,num2){
return num1+num2;
}
var res=test1(100,200);
2.函数作为方法调用
对象中可以包含属性和方法,对象的属性就相当于是变量,对象的方法可以使用函数来创建。
通过对象调用方法的方式来调用函数。
var student = {
method:function(num1,num2){
alert("有参数的函数");
}
}
student.method(120,200);
3.使用构造函数调用函数 -- 通过new 来调用函数
function test1(num1,num2){
return num1+num2;
}
var rest= new test1(100,200);
**********************************************
call()与apply()的区别?
call()与apply()的共同之处:
1.都是通过当前函数名称调用
2.call()与apply()的第一个参数是它们的返回值
call()与apply()的不同之处:
call()方法的参数从第二个开始是函数本身所需的参数值,逐一传入。
apply()方法的第二个参数是函数本身所需参数的数组。
两个方法都使用了对象本身作为第一个参数。
两者的区别在于第二个参数:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,
而call则作为call的参数传入(从第二个参数开始)。
**********************************************
JavaScript对象:
对象---用javascript语言描述现实中具体事物
用javascript语言现实中具体事物数据化以后得到
例如:我们写程序需要一辆汽车,计算机不能直接去使用一个在马路上行驶的汽车, 所以我们就需要将马路上行驶的汽车,使用javascript语言把汽车描述出来,这时程 序中描述出来的汽车就是一个汽车对象。
具体事物数据化--描述现实中具体事物---
1.事物的基本特征
2.事物的基本功能
对象中的元素包括:1.基本特征---属性
2.基本功能---方法【函数】
对象如何创建
1.字面量形式创建对象
--{}
--属性【键值对】
--方法【函数】
对象调用属性:对象名称.属性名称; / 对象名称["属性名称"];
对象调用方法: 对象名称.方法名称([参数]);
2.函数形式创建对象
---function
1.定义创建对象的函数
格式:
function 函数名称【首字母大写】(){
this.属性名称1="属性值1";
this.属性名称2="属性值2";
this.方法名称1=function(){};
this.方法名称2=function(num){};
this.方法名称3=function(num){return "hello"};
}
2.创建对象
var 对象名称=new 函数名称(参数);
例如:
var car1=new Car();
var car2=new Car("奔驰","黑色");
3.基于函数创建的对象,访问属性和方法
对象调用属性:对象名称.属性名称; / 对象名称["属性名称"];
var car1=new Car("奔驰","黑色");
car1.name; // 奔驰
对象调用方法: 对象名称.方法名称([参数]);
car1.myback("zhangsan");
3.使用Object创建对象
---Object
简化创建对象的过程,用Object代替创建对象的函数,每一创建对象的时候new Object();
对象的属性和方法没有给出。
用过new Object()得到的对象,赋值给出对象的属性和方法。
格式:
var 对象名称=new Object();
对象名称.属性名称1=属性值1;
对象名称.方法名称1=function(){};
例如:
var car=new Object();
car.name="bmw";
car.color="红色";
car.forword=function(){alert("forword方法");};
对象的分类
1.自定义对象---在编写程序的时候,自己定义创建的对象。
1.字面量形式创建对象---{}
2.函数形式创建对象----function【1.定义创建对象的函数 2.new】
3.使用Object创建对象----new Object()
2.内置对象-----javascript本身提供给我们使用的一组对象
1.高级对象
【Number(数字)对象 字符串(String)对象 Date(日期)对象 Boolean(布尔)对象
Math(算数)对象 RegExp(正则表达式)对象 Array(数组)对象】
2.DOM对象--【document对象 html元素对应的对象】
3.BOM对象---浏览器对象【window】
javascript中的高级对象
【Number(数字)对象 字符串(String)对象 Date(日期)对象 Boolean(布尔)对象
Math(算数)对象 RegExp(正则表达式)对象 Array(数组)对象】
变量就是对象
1.Number(数字)对象
1.创建Number(数字)对象
1.1变量就是对象
var num1=100;
alert(typeof num1); //number---基本数据类型
1.2 new Number()
var num3=new Number(123);
alert(typeof num3); //object----引用数据类型
基本数据类型number---》引用数据类型object---new
引用数据类型object---》基本数据类型number---- “=“
2.调用对象提供的属性和方法
属性:
Number.MAX_VALUE 最大值
alert(Number.MAX_VALUE);//1.7976931348623157e+308
Number.MIN_VALUE 最小值
alert(Number.MIN_VALUE); //5e-324
方法:
Number.parseFloat() 将字符串转换成小数,和全局方法 parseFloat() 作用一致。
var res1=Number.parseFloat("12.5");
alert(res1+"--"+typeof res1);
Number.parseInt() 将字符串转换成整型数字,和全局方法 parseInt() 作用一致。
var res2=Number.parseInt("120");
alert(res2+"--"+typeof res2);
Number.isNaN() 判断传递的参数是否为isNaN()。【非数字=true 数字=false】
var res3=isNaN("hello");//true
var res3=isNaN("120");//false
var res3=isNaN(120);//false
数字类型原型上的一些方法
toFixed()返回指定小数位数的表示形式。[返回值是字符串类型,会四舍五入]。
var num4=128.56739;
num4=num4.toFixed(3);
alert(num4+"--"+typeof num4);
原型与原型链
原型链(别名:隐式原型链)
访问一个对象属性时,
先在自身属性中查找,找到返回
如果没有,再沿着__proto__这条链向上查找,找到返回
如果最终没有找到,则返回undefined
作用:
1.查找对象的属性(方法)
2.构造函数/原型/实体对象的关系
3.构造函数/原型/实体对象的关系2
<script>
// console.log(Object);
// console.log(Object.prototype);
console.log(Object.prototype.__proto__);
function Fn(){
this.test1 = function(){
console.log("test1()");
};
}
console.log(Fn.prototype);
Fn.prototype.test2 = function(){
console.log("test2()");
};
var fn = new Fn();
fn.test1();
fn.test2();
console.log(fn.toString());
console.log(fn.test3);
// fn.test3();
/* 1.函数的显示原型指向的对象默认是空Object实例对象(但Object不满足) */
原型链属性问题
1.读取对象的属性值时,会自动到原型链中查找
2.设置对象的属性值时,不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
3.方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
原型简写
*************************************************
面试题
<script>
/* 测试题1*/
function A(){}
A.prototype.n = 1;
var b = new A();
A.prototype = {
n:2,
m:3
};
var c = new A();
console.log(b.n,b.m,c.n,c.m); //1 undefined 2 3
/* 测试题2 */
function F(){}
Object.prototype.a = function(){
console.log("a()");
};
Function.prototype.b = function(){
console.log("b()");
};
var f = new F();
f.a();
// f.b(); 不能执行
F.a();
F.b();
console.log(f);
console.log(Object.prototype);
console.log(Function.prototype);
</script>
*************************************************
继承模式
3.2.1原型链继承
原型链继承:方式一
套路:
1.定义父类型的构造函数
2.给父类型的原型添加方法
3.定义子类型的构造函数
4.创建父类型的对象赋值给子类型的原型
5.将子类型原型的构造属性设置为子类型
6.给子类型原型添加方法
7.创建子类型的对象:可以调用父类型的方法
关键
- 子类型的原型为父类型的一个实例对象
借用构造函数继承
方式二:借用构造函数继承(假的)
1.套路:
- 定义父类型的构造函数
- 定义子类型的构造函数
- 在子类型构造函数中调用父类型构造
2.关键:
- 在子类型构造函数中通用call()调用父类型构造函数
组合继承
方式三:原型链+借用构造函数的组合继承
1.利用原型链实现对父类型对象的方法继承
2.利用call借用父类型构造函数初始化相同属性
作用域与作用域链
作用域
1.理解:
- 指一块空间,代码所在的区域
- 它是静态的(相对于上下文对象),在编写代码时就确定了
2.分类:
- 全局作用域
- 函数作用域
- 没有块作用域(ES6开始有了)
3.作用:
- 隔离变量,不同作用域下同名变量不会有冲突
1 作用域与执行上下文
作用域与执行上下文的区别:
区别1
- 全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了,而不是在函数调用时,
- 全局执行上下文环境是在全局作用域确定之后,js代码马上执行之前创建
- 函数执行上下文是在调用函数时,函数体代码执行之前创建
区别2
- 作用域是静态的,只要函数定义好了就一直存在,且不会再变化
- 执行上下文是动态的,调用函数时创建,函数调用结束时就会自动释放
联系
- 上下文环境(对象)是从属于所在的作用域
- 全局上下文环境–>全局作用域
- 函数上下文环境–>对应的函数作用域
闭包
1理解闭包
1.如何产生闭包?
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。
2.闭包到底是什么?
理解一:闭包是嵌套的内部函数
理解二:包含被引用变量(函数)的对象
注:闭包存在于嵌套的内部函数中
3.产生闭包的条件?
函数嵌套
内部函数引用了外部函数的数据(变量/函数)
<script>
function fn1(){
var a = 2;
var b = "abc";
function fn2(){ //执行函数定义就会产生闭包(不用调用内部函数)
console.log(a);
}
fn2();
}
fn1();
</script>
2常见的闭包
1.将函数作为另一个函数的返回值
2.将函数作为实参传递给另一个函数调用
3闭包的作用
闭包的作用
1.使用函数内部的变量在函数执行完后,仍然存活在内存中(延长了局部变量的生命周期)
2.让函数外部可以操作(读写)到函数内部的数据(变量/函数)
问题:
1.函数执行完后,函数内部声明的局部变量是否还存在?
一般是不存在的,存在于闭包的变量才可能存在
2.在函数外部能直接访问函数内部的局部变量么?
不能,但我们可以通过闭包让外部操作它
4闭包的应用_自定义JS模块
闭包的应用:自定义JS模块
- 具有特定功能的js文件
- 将所有的数据和功能都封装在一个函数内部(私有的)
- 只向外暴露一个包,执行n个方法的对象或函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
局部变量
闭包的作用:在当前函数之外来访问当前函数的局部变量。
「函数」和「函数内部能访问到的变量」
闭包会造成内存泄露?错。
内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。
闭包里面的变量明明就是我们需要的变量(lives),凭什么说是内存泄露?
因为 IE。IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。
这是 IE 的问题,不是闭包的问题。参见司徒正美的这篇文章【https://www.cnblogs.com/rubylouvre/p/3345294.html】
原型和原型链
原型和原型链是JavaScript进阶重要的概念。
尤其在插件开发过程中是不能绕过的知识点。
函数中的this
this是什么?
- 在任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
- 所有函数内部都有一个变量this
- 它的值是调用函数的当前对象
如何确定this的值?
- test(); window
- p.test(); p
- new test(); 新创建的对象
- p.call(obj); obj
<script type="text/javascript">
function Person(color) {
console.log(this)
this.color = color;
this.getColor = function () {
console.log(this)
return this.color;
};
this.setColor = function (color) {
console.log(this)
this.color = color;
};
}
Person("red"); //this是谁? window
var p = new Person("yello"); //this是谁? p
p.getColor(); //this是谁? p
var obj = {};
p.setColor.call(obj, "black"); //this是谁? obj
var test = p.setColor;
test(); //this是谁? window
function fun1() {
function fun2() {
console.log(this);
}
fun2(); //this是谁? window
}
fun1();
</script>
函数的调用方式决定了 `this` 指向的不同:
调用方式 | 非常严格模式 | 备注 |
普通函数调用 | window | 严格模式下是undefind |
构造函数调用 | 实例对象 | 原型方法中this也是实力对象 |
对象方法调用 | 该方法所属对象 | 紧挨着的对象 |
事件绑定方法 | 绑定事件对象 | |
定时器函数 | window |
◼ 这就是对函数内部 this 指向的基本整理,写代码写多了自然而然就熟悉了。
函数进阶-call、apply、bind
那了解了函数 this 指向的不同场景之后
我们知道有些情况下我们为了使用某种特定环境的 this 引用,这时候时候我们就需要采用一些特殊手段来处理了,例如我们经 常在定时器外部备份 this 引用,然后在定时器函数内部使用外部 this 的引用。
然而实际上对于这种做法我们的 JavaScript 为我们专门提供了一些函数方法用来帮我们更优雅的处理函数内部 this 指向问题。这 就是接下来我们要学习的 call、apply、bind 三个函数方法。
小结
◼ call 和 apply 特性一样
◼ 都是用来调用函数,而且是立即调用
◼ 但是可以在调用函数的同时,通过第一个参数指定函数内部 `this` 的指向
◼ call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可 ◼ apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行 传递
◼ 如果第一个参数指定了 `null` 或者 `undefined` 则内部 this 指向 window
◼ bind
◼ 可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
◼ 它和 call、apply 最大的区别是:bind 不会调用
◼ bind 支持传递参数,它的传参方式比较特殊,一共有两个位置可以传递
◼ 1. 在 bind 的同时,以参数列表的形式进行传递
◼ 2. 在调用的时候,以参数列表的形式进行传递
◼ 那到底以谁 bind 的时候传递的参数为准呢还是以调用的时候传递的参数为准
◼ 两者合并:bind 的时候传递的参数和调用的时候传递的参数会合并到一起,传递到函数内部