js知识总结(递归、作用域和预解析)
一:回顾
二:静态成员和实例成员:
- 静态成员:通过构造函数访问的成员 >> 函数名.成员
- 实例成员:通过实例对象访问的成员 >> 实例对象.成员
三:递归:
- 两个前提:调用自己-有结束条件
简单示例:
查找元素的所有子元素:先找到直接子元素,再查找子元素的子元素
function getChilds(element){
var list=[];
var childs=element.children;
for (var i = 0; i < childs.length; i++) {var child=childs[i]; list.push(child); var subList=getChilds(child); 将返回值拼接到原始的list中 list=list.concat(subList);
}
return list;
}window.onload=function(){
var header=document.querySelector(“header”);
var myList=getChilds(header);
console.log(myList);
}
四:作用域:
- 概念:变量起作用的范围
- 在js中,只有函数可以创建作用域
- 词法作用域(静态作用域):根据代码的书写结构去确定变量的作用范围,与调用没有关系。意味着在使用一个变量的时候,首先在自己的作用域中查找,如果没有就去上一级作用域中查找
- 注意:js中没有块级作用域,意味着在if或者for中定义的变量在它们的外部也能够访问
五:变量名提升:
- js代码的执行过程包含:预解析和执行
- 在代码的预解析阶段,js引擎会将所有的变量声明,以及函数声明提升到其所在的作用域的最顶端
- 当函数和函数同名,都会进行提升,造成后面声明的函数覆盖前面的函数
- 当函数和变量名同名的时候,只会提升函数,忽略变量的声明
- 用表达式创建的函数不能进行提升,只有对应的变量名称能够进行提升
- 条件式函数声明:就是在条件语句是声明的函数,在变量提升的时候会被当函数表达式来处理
变量提升是分Script标签的。所有的全局的函数或者变量的声明,只会被提升到当前Script标签的最顶端
六:函数的作用域链:
1.只有函数可以创建作用域
2.在函数中可以嵌套函数,这样就形成了作用域中嵌套另外一个作用域,这就形成了作用域链
3.作用域链中变量的搜索原则:
a.首先在当前使用变量的作用域中查找,如果找到就使用,否则查找上一级作用域
b.查找上一级作用域,如果找到就使用,否则再查找上一级作用域
c.如果没有,就一直沿着作用域往上找,直到找到全局的作用域为止
4.访问规则:由内至外
a.内层作用域可以访问外层作用域中的变量
b.外层作用域不能直接访问内层作用域中的变量*/var num;
function f1(){
var num;
function f2(){console.log(num);
}
num=123;
f2();
}
num=234;
f1();
七:Object.defineProperty
- 作用:这个方法会直接在一个对象上定义一个新的属性或者修改一个已经存在的属性,并返回这个对象。
- 语法:Object.defineProperty(obj,prop,descriptor)
a) Obj:要添加属性或者修改属性的对象
b) Prop:要修改或者添加的属性名称
c) Descriptor:标记属性能否被删除,修改或者遍历。。。相当于配置属性的特性,它是一个对象 - 代码示例:
var obj={};
第一个参数:需要添加属性的对象
第二个参数:属性名称
第三个参数:它是一个对象,用来配置当前属性的特性
writable:true:是否可以赋值,默认是false
configurable:设置属性是否可以被配置(如删除),默认为false
enumerable:设置属性能否被遍历,默认为false
value:设置当前属性的默认值
get:获取值 –只读属性
set:赋值,可以进行数据的合法性校验 –只写属性
Object.defineProperty(obj,’name’,{
//writable:true,
//configurable:true,
enumerable:true,
//value:’jack’,
/get、set不能和value和writable一起使用/
/获取属性值/
get:function(){
},return obj._name;
/为属性赋值/
set:function(value){
}console.log('方法被调用了'); /*这里一般可以做参数值的验证*/ if(typeof value !="string"){ throw '请输入合法的用户名'; } obj._name=value;
});
obj.name=10;
//delete obj.name;
console.log(obj);
for(var key in obj){
console.log(key);
} - 注意:get/set方法不能和value和writable属性一起使用。