JS对象与面向对象

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属性和方法

当函数被作为面向对象的类使用时,函数中的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();

 原型链  __proto__  针对对象
   原型  prototype  针对类


猜你喜欢

转载自blog.csdn.net/xiaoming0018/article/details/80342522