Window.onload加载完成后执行
obj.name 点语法调用对象的属性name
obj["name"] 关键字调用对象的属性name obj[str]=属性值 str属性名
删除对象时要先将内容先赋空然后在删除
数组是紧密型的数据存储容器,对象是松散型的存储容器
js是根据属性的添加顺序打印
for() 根据下标变量来循环整个数组的,所以只能找到数组的元素,但是不能找到数组的属性 for(in) 不但可以找到所有元素,也可以找到所有的属性和方法
for(var i in arr){} i有arr的所有属性 对象循环只能用for(in) 循环对象属性
window ===this所有的变量,函数都是window属性和方法
函数.call(null, 3,5)执行函数,并且替代函数中的this为带入的对象,函数参数逐一填入
用call的时候,第一个参数是替代参数,用来替代函数中的this这个参数如果是null,函数中的this仍然是原有的this作用如果这参数是别的对象,函数中的this就是这个对象
delete obj.a;删除对象下的属性
delete obj1.abc(); 执行了abc的方法,但是没有删除这个方法
delete obj1.abc 删除abc的方法
如果delete删除数组的元素时,数组变为松散型数组,长度不变化
Object.assign(obj1,obj2) 把obj2的所有属性添加并且合并到obj1上
obj3=Object.assign({},obj1,obj2);assign具备返回新的对象,这个对象就是空对象 将obj1和obj2合并并且传递给obj3;复制合并后的对象与原对象不存在引用关系,不会因为原对象的值改变而改变
writable 是否可写
configurable 是否可写可删除
enumerable 是否可被枚举
Object.defineProperties(obj,obj2);
给obj对象添加新的属性对象或者可以理解为给obj的属性上添加obj2的所有属性
obj2的所有属性,定义时,属性值的定义是一个对象,含有四个内容,value,writable configurable,enumerable 定义该属性是否可写
Object.defineProperty(obj,"属性名",{属性值})
defineProperty定义对象obj的一个属性,这个属性值包含有4个属性内容 包括可写,可枚举,可删除,值
Object.getOwnPropertyDescriptor(obj,"属性名")获取对象下属性名的对应详细特征对象
Object.getOwnPropertyNames(obj)获取对象下所有属性名,并以数组返回。可以看到不可枚举的属性等
Object.freeze(obj);冻结obj,实际上是修改对象下所有的属性中的不可写不可删除属性为false
替代this。带入需要替代this的对象,如果带入的时null,this仍未原有的含义call apply bind
setter 当设置这个值时,我们可以执行对应这个函数,这个函数中可以写任何程序
getter 获取这个值时,可以执行对应这个函数,这个函数可以写任何程序
仅设置setter 就是只可写不可读 仅设置getter 就是只可读不可写
因为setter和getter是不可枚举属性,我们如果需要将这种属性赋值给其它对象时
* 1、先获取该对象下的所有属性名
* 2、循环所有属性
* 3、获取每个属性的特征对象
如何读取局部变量的值?
用函数return局部变量在用另一个函数访问这个函数,
案例中fun1是一个函数,里面套叠了一个fun2的函数,因为fun2和a
从属一个作用域下,因此可以返回a的值最后我们执行的最后把fun2这个函数通过fun1返回出去。因此fun1()执行以后就是fun2,而fun2要执行就需要给他再加一个(),因此就变成了fun1()();你也可以通过赋值的方法将它拆解开,例如
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
清除闭包让闭包等于null
闭包的特点和优点
闭包的特点
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
闭包的优点
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在
回调函数的机制
⑴定义一个回调函数;
⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
函数调用机制
任何函数之间不能嵌套定义, 调用函数与被调用函数之间相互独立(彼此可以调用)。 发生函数调用时,被调函数中保护了调用函数的运行环境和返回地址,使得调用函数的状态可以在被调函数运行返回后完全恢复,而且该状态与被调函数无关。
被调函数运行的代码虽是同一个函数的代码体,但由于调用点,调用时状态, 返回点的不同,可以看作是函数的一个副本,与调用函数的代码无关,所以函数的代码是独立的。被调函数运行的栈空间独立于调用函数的栈空间,所以与调用函数之间的数据也是无关的。函数之间靠参数传递和返回值来联系,函数看作为黑盒。
递归调用有直接递归调用和间接递归调用两种形式。
递归的条件
(1)须有完成函数任务的语句。
(2)—个确定是否能避免递归调用的测试
(3)一个递归调用语句。 该递归调用语句的参数应该逐渐逼近不满足条件,以至最后断绝递归。
(4)先测试,后递归调用。
在递归函数定义中,必须先测试,后递归调用。也就是说,递归调用是有条件的,满足了条件后,才可以递归。
递归的评价
原型链 __proto__ 针对对象
obj.name 点语法调用对象的属性name
obj["name"] 关键字调用对象的属性name obj[str]=属性值 str属性名
删除对象时要先将内容先赋空然后在删除
数组是紧密型的数据存储容器,对象是松散型的存储容器
js是根据属性的添加顺序打印
for() 根据下标变量来循环整个数组的,所以只能找到数组的元素,但是不能找到数组的属性 for(in) 不但可以找到所有元素,也可以找到所有的属性和方法
for(var i in arr){} i有arr的所有属性 对象循环只能用for(in) 循环对象属性
window ===this所有的变量,函数都是window属性和方法
当函数被作为面向对象的类使用时,函数中的this,不再是window。而是被实例化的对象
new 函数名() 实例化对象,函数就是面向对象的类
替代对象
函数.apply(null,[arr]) 执行函数,并且替代函数中的this为带入的对象,函数的参数需要用数组来写入函数.call(null, 3,5)执行函数,并且替代函数中的this为带入的对象,函数参数逐一填入
用call的时候,第一个参数是替代参数,用来替代函数中的this这个参数如果是null,函数中的this仍然是原有的this作用如果这参数是别的对象,函数中的this就是这个对象
delete obj.a;删除对象下的属性
delete obj1.abc(); 执行了abc的方法,但是没有删除这个方法
delete obj1.abc 删除abc的方法
如果delete删除数组的元素时,数组变为松散型数组,长度不变化
Object.assign(obj1,obj2) 把obj2的所有属性添加并且合并到obj1上
obj3=Object.assign({},obj1,obj2);assign具备返回新的对象,这个对象就是空对象 将obj1和obj2合并并且传递给obj3;复制合并后的对象与原对象不存在引用关系,不会因为原对象的值改变而改变
writable 是否可写
configurable 是否可写可删除
enumerable 是否可被枚举
Object.defineProperties(obj,obj2);
给obj对象添加新的属性对象或者可以理解为给obj的属性上添加obj2的所有属性
obj2的所有属性,定义时,属性值的定义是一个对象,含有四个内容,value,writable configurable,enumerable 定义该属性是否可写
Object.defineProperty(obj,"属性名",{属性值})
defineProperty定义对象obj的一个属性,这个属性值包含有4个属性内容 包括可写,可枚举,可删除,值
Object.getOwnPropertyDescriptor(obj,"属性名")获取对象下属性名的对应详细特征对象
Object.getOwnPropertyNames(obj)获取对象下所有属性名,并以数组返回。可以看到不可枚举的属性等
Object.freeze(obj);冻结obj,实际上是修改对象下所有的属性中的不可写不可删除属性为false
Object.is("",false)与===相同
函数中的this代表window
function abc() { console.log(this);//window; } abc(); console.log(this);//window事件函数中的this,与e.currentTarget相同,就是事件侦听的对象e.target是事件触发的目标
替代this。带入需要替代this的对象,如果带入的时null,this仍未原有的含义call apply bind
setter 当设置这个值时,我们可以执行对应这个函数,这个函数中可以写任何程序
getter 获取这个值时,可以执行对应这个函数,这个函数可以写任何程序
仅设置setter 就是只可写不可读 仅设置getter 就是只可读不可写
因为setter和getter是不可枚举属性,我们如果需要将这种属性赋值给其它对象时
* 1、先获取该对象下的所有属性名
* 2、循环所有属性
* 3、获取每个属性的特征对象
* 4、给新的对象中添加这个属性,和特种对象
var obj={ _a:1, sum:0, abc:function () { }, set a(value){ this._a=value; }, get a(){ if(this._a<5){ return 0; } return this._a; } };
传递对象中不可枚举的属性
var obj1={s:5}; var arr=Object.getOwnPropertyNames(obj); for(var i=0;i<arr.length;i++){ var proObj=Object.getOwnPropertyDescriptor(obj,arr[i]); Object.defineProperty(obj1,arr[i],proObj); } console.log(obj1); var obj={a:3,b:4};//集合 var obj1={a:{a1:4,a2:5},b:{b1:6,b2:7}};//多重集合
闭包作用域
要理解闭包,首先必须理解Javascript特殊的变量作用域。 变量的作用域无非就是两种:全局变量和局部变量。 Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。var a=6 function fun1(){ console.log(a) } fun1(); 变量a是全局变量 var a=6 function fun1(){ var b=6; } fun1(); console.log(b)b是私有变量注意:如果b=6前面不写var,b就被升级为全局变量了
如何读取局部变量的值?
用函数return局部变量在用另一个函数访问这个函数,
案例中fun1是一个函数,里面套叠了一个fun2的函数,因为fun2和a
从属一个作用域下,因此可以返回a的值最后我们执行的最后把fun2这个函数通过fun1返回出去。因此fun1()执行以后就是fun2,而fun2要执行就需要给他再加一个(),因此就变成了fun1()();你也可以通过赋值的方法将它拆解开,例如
var fun=fun1(); var a1=fun(); console.log(a1); function fun1(){ var a=6; function fun2(){ return a; } return fun2; } console.log(fun1()())什么是闭包
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量
清除闭包让闭包等于null
闭包的特点和优点
闭包的特点
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
闭包的优点
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在
嵌套函数的闭包
定义的函数fun1,里面有一个sum,前面我们说过return是可以返回任何值得,包括函数,因此在该案例中我们直接返回一个function函数,这样的写法等同于右图。同样嵌套执行以后,因为fun1这个函数执行后保存为了变量fun2,也就是说fun2就是fun1内部那个匿名函数,因此在执行fun2后就执行了一次fun1中的那个匿名函数,fun2是被保存到了外部变量,所以函数运行完后sum并没有被清理掉,因为外面有对于这个匿名函数的引用,因此,再次执行时,sum被继续连加。直到最后fun2被赋值为null的时候,fun1当中的匿名函数引用才被切断,这时候也把这个sum清理掉了。
function fun1(){ var sum=1; return function(){ sum++; return sum; } } var fun2=fun1(); console.log(fun2()); console.log(fun2()); fun2=null
闭包内的作用域
fun1是作为一个自执行函数返回定义的,因此fun1实际上是返回的对象,而对象下有一个方法sum,因此fun1,sum就是调用该对象下的sum方法,注意,a是自执行函数的私有变量,b是对象的共有属性,因此,调用b的时候this.b可以在对象内调用,也可以在外部使用this.b调用,但是在外部是无法调用变量a的,因为他是局部变量。var fun1=(function(){ var a=3; return { b:7, sum:function(){ return this.b+a; } } })() console.log(fun1.sum());
回调
就是将函数作为参数带入另一个函数中,当需要的时候执行函数回调函数的机制
⑴定义一个回调函数;
⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。
递归
递归函数即自调用函数,在函数体内部直接或间接地自己调用自己,即函数的嵌套调用是函数本身。或者两个函数的相互调用。函数调用机制
任何函数之间不能嵌套定义, 调用函数与被调用函数之间相互独立(彼此可以调用)。 发生函数调用时,被调函数中保护了调用函数的运行环境和返回地址,使得调用函数的状态可以在被调函数运行返回后完全恢复,而且该状态与被调函数无关。
被调函数运行的代码虽是同一个函数的代码体,但由于调用点,调用时状态, 返回点的不同,可以看作是函数的一个副本,与调用函数的代码无关,所以函数的代码是独立的。被调函数运行的栈空间独立于调用函数的栈空间,所以与调用函数之间的数据也是无关的。函数之间靠参数传递和返回值来联系,函数看作为黑盒。
递归调用有直接递归调用和间接递归调用两种形式。
递归的条件
(1)须有完成函数任务的语句。
(2)—个确定是否能避免递归调用的测试
(3)一个递归调用语句。 该递归调用语句的参数应该逐渐逼近不满足条件,以至最后断绝递归。
(4)先测试,后递归调用。
在递归函数定义中,必须先测试,后递归调用。也就是说,递归调用是有条件的,满足了条件后,才可以递归。
递归的评价
递归的目的是简化程序设计,使程序易读。但递归增加了系统开销。 时间上, 执行调用与返回的额外工作要占用CPU时间。空间上,随着每递归一次,栈内存就多占用一截。相应的非递归函数虽然效率高,但却比较难编程,而且相对来说可读性差。 现代程序设计的目标主要是可读性好。随着计算机硬件性能的不断提高,程序在更多的场合优先考虑可读而不是高效,所以,不鼓励用递归函数实现程序思想。
获取所有的id用递归
varobj={}; functiongetObjData(elem){ if(elem.id.length>0){ obj[elem.id]=elem; } for(vari=0;i<elem.children.length;i++){ getObjData(elem.children[i]); } } getObjData(document.body); console.log(obj);
创建对象 原型中的属性优先于构造函数中的属性
类原型
function Box(w,h) { this.width=w; this.height=h; this.sum=5; this.backgroundColor="#FF0000";
构造函数法 var box1=new Box(100,200); 函数名首字母大写
对象创建法
var Boxs={ width:100, height:100, set sum(value){ this.width=value; } }; Object.creates=function(o){ functionZhang(){} Zhang.prototype=o; returnnewZhang(); }; varbox3=Object.create(Boxs); varbox4=Object.creates(Boxs);
极简主义法
var Boxss={ createBox:function () { var o={}; o.width=100; o.height=100; return o; } }; var box5=Boxss.createBox();