js面向对象学习
全局预处理
解析js代码的时候,预处理阶段
第一步:创建一个环境对象
接下来扫描代码里的用声明的方式创建的函数,还有用var定义的变量
然后将所有的函数的名字和变量的名字放到环境对象中
function a(){}和var b=3这两种
函数还有一种用函数表达式的定义的,var a=function(){},这种叫函数表达式,不是生命的方式定义函数.
在于处理阶段 变量 b:undefinde
全局预处理与执行
处理函数声明有冲突,会覆盖
处理变量生命是有冲突,会忽略
变量需要先声明后使用
执行阶段会把变量的undefined换成对应的数据,把undefined的函数表达式换成对应的函数
函数的预处理与执行
function d(a,b) {
alert(a)
alert(b)
function a() {
console.log(‘aaa’)
}
}
d(1,3)
//function a() {
console.log(‘aaa’)
}
//3
每一个function都是一个词法环境,在d函数中,a被函数a重新定义了,所以会被覆盖,所以输出结果如上
如果函数里面的变量没有用var声明,则该变量最终会挂到window上面
作用域
在预处理阶段扫描变量的时候,会忽略判断条件,会把if是false里面的变量也会扫描
块作用域:变量在离开定义的块级代码后立即被回收。
es6之前js只有函数作用域和全局作用域,使用var声明的变量,都存在变量提升的过程
es6之后有了let,let不会变量提升.有块作用域
for循环不会有块作用域
eg:for(var i=0;i< 3;i++){ }
alert(i)//3
for(let i=0;i< 3;i++){ }
alert(i)//i is not defined
函数作用域
内层函数无法访问外层函数的变量
动态作用域
js无动态作用域
词法作用域(静态作作用域或闭包)
内部函数首先在自己的作用域内找变量,找不到再向外层找,从里到外一层一层往外找,直到window
js里面创建函数的几种方法:
1.function f(){}
2.var f=function(){}
3.var f=function x(){}
function f() {
var x=100;
var g=function () {
alert(x)
}
g()
}
f()//100
(function f() {
var x=100;
var g=function () {alert(x)}
g()
})();//匿名函数外面加上(function(){})();,函数会立即调用
4.var f=new Function(参数,{函数体}){} //作用域永远是window
var x=10
function f() {
var x=100;
var g = new Function ('','alert(x)')
g()
}
f()//10
function f() {
var x=100;
var g = new Function ('','alert(x)')
g()
}
f()//x undefined
内部变量的好处:自动创建,自动销毁.
闭包的含义
闭包是词法闭包的简称,是引用了自由变量的函数
闭包是由函数和与其相关的引用环境组合而成的实体.
自己的理解:闭包其实就是函数外部读取函数内部的变量
unction f() {
var x=100;
return function g () {
alert(x)
}
}
var result=f()
result()//100
闭包的理解
如果内部函数不用外部函数的变量,或者是用的window环境的变量,这两个情况其实是不存在闭包的.
创建的时间:就是当内部函数引用父函数的变量的时候.
闭包的好处
1.减少全局变量
function f() {
var x=0;
return function g () {
x++
alert(x)
}
}
var result = f();
result();
result();
//上面的代码调用两次result()方法,分别弹出1和2.x在第一次调用之后保持得到的值
2.减少传递给函数的参数的数量
function f(base) {
var total=0;
return function g (max) {
for(var i=0;i<=max;i++){
total+=i;
}
return total+base
}
}
var result = f(2);
alert(result(3));//8
alert(result(3));//14
var result1= f(1)
alert(result1(1))//2
3.封装
(function() {
var m=0;
function getM(){
return m;
}
function setM(val){
m=val
}
window.g=getM;
window.s=setM;
})();
s(12)
alert(g())//12
使用闭包的注意点
对捕获的变量只是一个引用,不是复制.
父函数每调用一次,会产生不同的闭包//例如上面的2.减少传递给函数的参数的数量中的代码
var i;
for(i=1;i<4;i++){
var el=document.getElementById(i)
// el.onclick=(function (id) {
// return function () {
// alert(id);//1,2,3,4
// }
// })(i);
el.onclick=function () {
alert(i) //4,4,4,4
}
}
对象的创建与访问
js的五大数据类型:undefined,null,String,boolean,number.
还有array,Object,
对象的种类:number,宿主环境window,自己创建的对象.
对象的三种创建方式
1.对象字面量形式
eg:
var p = {
name:'wangjj',
work:function(){
alert('working')
},
_age:18,//下划线代表不要直接用
get age(){
return this._age
},
set age(val){
if(val<0||val>200){
throw new Error ('无效的年龄')
}else{
this._age=val
}
},
address:{
home:'home',
gongsi:'gongsi'
}
}
console.log(p.name) //18
p.age=30
console.log(p.age) //30
console.log(p['age']) //30 不同的访问方式,当对象属性的key是变量或者是数组特殊符号的时候访问,访问不存在的属性返回undefined,
2.成员访问
如上,不同的访问方式,当对象属性的key是变量或者是数组特殊符号的时候访问,访问不存在的属性返回undefined,
级联访问:console.log(p.address.gongsi)//gongsi
var result= p&&p.address&&p.address.home//三个条件任何一个为空,result就是空
3.Object构造器创建对象