函数函数的作用:
1.功能的封装,直接调用,代码复用率提高
2.构建对象的模板(构造函数)
3.函数实际上是对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法,由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
1.函数声明
function 函数名(形参列表){
函数体
return
写在return后面代码,除了var会变量提升,其他都会忽略
}
接收返回值结果
var a=函数名(实参列表)2.函数表达式
var 函数名(f1)=function(形参列表){
//函数体
}
f1()
3.函数提升
f1();
function f1(){
console.log(‘我是一个函数’)
}
f1()
1.函数的提升会放在作用域的最顶部
2.有使用var声明得变量在函数提升之后进行变量提升
3.var声明变量和函数名重复,忽略var得值
console.log(test);
var test=1;
function test(){
} **
原型
每创建一个函数,该函数都会自动带有一个prototype属性。该属性是一个指针,指向一个对象,该对象称之为原型对象(后期我们可以使用这个原型对象帮助我们在js中实现继承).
原型对象上默认有一个属性constructor,该属性也是一个指针,指向其相关联的构造函数。
Js中new一个构造函数时,通过调用构造函数产生的实例对象,都拥有一个内部属性,指向了原型对象。其实例对象能够访问原型对象上的所有属性和方法。
1、原型:
①所有引用类型都有一个__proto__
(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__
属性指向它构造函数的prototype
2.原型链
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__
隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__
中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
①一直往上层查找,直到到null还没有找到,则返回undefined
②Object.prototype.proto === null
③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象
原文链接:https://blog.csdn.net/xiaoermingn/article/details/80745117
每一个构造函数都有一个原型对象
每一个原型对象都有一个构造者
Object原型属性及方法 (原型本身 实例可以调用)
constructor 保存用户创建当前对象的函数,与原型对象对应的构造函数
hasOwnProperty(propertyName) 检查给定的属性名是否是对象的自有属性
propertyIsEnumerable(propertyName) 检查给定的属性在当前对象实例中是否存在
valueOf() 返回对象的字符串,数值,布尔值的表示
toLocaleString() 返回对象的字符串表示,该字符串与执行环境的地区对应
toString() 返回对象的字符串表示
isPrototypeOf(object) 检查传入的对象的原型
定义属性
(1)数据属性
name age
数据属性特性
configurable 使用delete删除重新定义属性 默认true
Enumerable 是否可枚举 默认true
Writable 是否可写 默认true
value 要修改的属性特性
要修改属性默认特性
1.单个属性
Object.defineProperty(obj,‘name’,{//属性描述符
writrable:true
Enumerable:true
configurable:true
value:""
})
Object.defineProperty(obj,‘name’,{
writable:true,
enumerable:false,
configurable:false,
value:‘lll’
});
// obj.name=‘terry’;
delete obj.name;
console.log(obj.propertyIsEnumerable(‘name’));
console.log(obj);
2.多个属性
var obj=new Object();
Object.defineProperties(obj,{
name:{
writrable:true
Enumerable:true
configurable:true
value:‘terry’
},
age:{
value:20
}
})
3.查询对象自有属性的一些属性描述符
var obj1={
name:“lisi”
}
var a=Object.getOwnPropertyDescriptor(obj1,‘name’);
console.log(a);
(2)访问器属性
var obj={
_num:1,
count:1
}
Object.defineProperty(obj,‘num’,{
get:function(){
return this._num
},
set:function(newNum){
if(newNum!==this._num){
this._num=newNum;
this.count++
}
}
})
console.log(obj.num);
obj.num=21;
console.log(obj.num);
console.log(obj.count);
4.函数内部属性
1.arguments
用来保存实际参数列表的类数组对象,包含着传入函数中的所有参数。arguments主要用途是保存函数参数。
function f1(a,b){
console.log(a,b)
console.log(arguments)
console.log(typeof arguments) /object
console.log(arguments[3]) /4
console.log(f1.length);//形参的个数。
}
f1(1,2,3,4,5)
callee属性
该属性是一个指针,用来指向拥有这个arguments对象的函数
2.this 指向的是函数赖以执行的环境对象
谁调用指向谁
单独使用this,全局
浏览器中 window对象
node global对象
函数中使用this
在函数中,函数的所属者默认绑定到 this 上
事件中的 this
在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素
call apply改变this指向
.call(执行环境对象,实参列表);
.apply(执行环境对象,实参列表数组);
.bind(执行环境对象)(实参列表);
call 方法第一个参数是this的指向,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。如:getColor.call(obj,‘yellow’, ‘blue’, ‘red’)
apply 方法接受两个参数,第一个参数是this的指向,第二个参数是一个参数数组。当第一个参数为null、undefined的时候,默认指向window。如:getColor.apply(obj,[‘yellow’, ‘blue’, ‘red’])
bind 方法和 call方法很相似,第一个参数是this的指向,从第二个参数开始是接收的参数列表。区别在于bind方法返回值是函数以及bind接收的参数列表的使用。低版本浏览器没有该方法,需要自己手动实现
3.IIFE
11.作用域链
常见的作用域主要分为几个类型:全局作用域、函数作用域、块状作用域
对象 | 类型 |
---|---|
global/window | 全局作用域 |
function | 函数作用域(局部作用域) |
{} | 块状作用域 |
声明在函数内部,局部变量
var a=10;
console.log(a)
function a(){
var a=1;
console.log(a)
}
a();
逐层向上级作用域查找形成全局作用域,形成一个链
12.闭包
闭包:函数内部包裹函数,作用域链得不到释放,造成消耗内存。
闭包的本质就是在一个函数内部创建另一个函数。
可以读取其他函数内部变量的函数
–产生
var a=1;
function f1(){
var b=2;
console.log(a)
}
console.log(a)
局部变量无法共享和长久地保存,而全局变量可能造成污染,
当我们希望有一种机制即可以长久地保存变量又不会造成全局污染。
优点:
①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)。
③匿名自执行函数可以减少内存消耗。(function(){}){}
坏处:
①被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null;
②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响
解决方法:
立即执行函数,创建函数后就立即执行
IIFE
- 页面加载完成后只执行一次的设置函数。
- 将设置函数中的变量包裹在局部作用域中,不会泄露成全局变量。
//闭包满足条件:返回的是一个函数且这个函数对局部变量存在引用,这就形成闭包包含关系。
局部变量没有被回收,而是保留了下来
function f1(){
var x=10;
function f2(){
x++;
console.log(x)
}
return f2
}
var f1=f1() //f1执行的结果赋给了全局变量,f1返回的结果存在全局变量中,不会被回收
f1()
function f2(){
var a=10;
a++;
return a
}
f2() //相当于重新每一次执行f2