对象
复合数据类型,为引用数据类型,在对象中可保存多个不同的数据类型的属性
直接创建的对象都是Object的实例对象
内建对象:标准对象 Math String 等
宿主对象:由js运行环境提供的对象,bom dom
自定义对象:由开发人员自建的对象
创建对象,赋予属性和属性值
1 构造函数创建对象创建对象:var obj = new Object();
使用new关键字调用的为构造函数,用于创建新的对象
向对象中可保存的内容有属性 obj.name = ‘XX’ 属性的定义及赋值
使用时,对象.属性名 获取属性值
如果读取没有的属性,不会报错但是会返回undefined
删除属性:delete obj.name;
两种方式取属性 1 obj.name 2 obj[‘name’] 对第二种方式来说,除了直接传值,还可以传变量,比如用 n=name,然后obj[n]这样同样可以取到,不是变量时候[]内的必须带引号
属性值:可以是任意的数据类型(包括对象)
直接赋值对象给对象,等于引用,修改被复制的对象,复制的对象将同样反馈其变化,即基本类型的赋值是有值,则复制值,而对引用类型的,赋值赋的是内存地址,改变值后,查找的是同样的内容
对象是保存在堆内存中的,每new一个对象,则用变量保存其的地址信息,具体的属性及属性值讲保存至堆内存中,当比较基本数据类型时候,比较的是值,如果比较的是对象,则比较的是地址
"属性名" in obj 运算符 检查属性名是否存在于对象内
2、简写对象(字面量)创建: var obj ={};
var obj = {name : ‘张三’,age:20,…………} 在创建时直接赋值,属性在不是不规范数据时,可不加引号
3、工厂方式创建对象,本质还是构造函数
function creatObj(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
return obj;
}
函数
函数也是一个对象,封装一些功能,在需要时候执行
var fun = new Function();
可把代码以字符串的形式传给构造函数,封装好的函数,需要在调用时候执行,也可给fun加属性,用fun.属性去创建,但是不太好。
一般使用 function 函数名(参数组){语句}
使用函数表达式来创建:
var 函数名 = function(参数){ 代码 }
参数:定义形参,无法指定类型,在调用时候,将实参赋值给对应的形参,调用解析器时候不会解析实参类型,因此需要注意检查数据类型,解析器也不会检查实参数量,多余的不会赋值,如果少了时候,将会为undefined
return可返回函数的执行结果。在return后的内容将不会再执行,结束了整个函数
实参可以是任何值,可在里面传任何值,包括函数,常用直接在实参里面直接带入实参内
注意不带括号参数,表示将复制函数的地址给新的对象此对象以后同样只带函数,带括号表示只是将做参数的函数执行结果当参数传给函数
return同实参一样,可以返回任意值,如果返回函数,可以同时括号两个,意思在执行return的函数
立即执行函数
对匿名函数,加一个括号表示这是一个结果,就不会报错了,对这种函数,如果后面加个括号,就立即执行了,执行完了就销毁
方法
对象的属性可以是函数,即为对象的方法
对象的遍历/枚举
遍历数组用for,遍历对象用for in,在对象中有几个属性执行几次,每次执行 将会将属性名复制给变量,如果想要值,可以用对象[变量]来取值
for(var key in obj){
console.log(key+obj[key])
}
作用域
1、直接编写再script内的,为全局作用域,在页面打开时创建,在页面关闭后销毁
在全局作用域中,有一个全局对象window,可直接使用 在全局作用域中,变量均作为window的对象,函数作为window的方法保存
变量的声明提前
用var声明的内容,将在最开始执行,如果不写var,将在执行时候再声明
函数的声明提前
用function声明的内容,将在代码声明前创建
全局变量在页面任意位置可见
2、写在函数内的,为函数作用域,调用函数时候生成,函数执行后销毁,每调用一次时候,创建1个新的函数作用域,期间相互独立的
在函数作用域中,可访问到全局变量
在函数内,优先访问函数内的变量,采取就进原则
如果想在函数里面找全局变量,可以用window.变量来找
在函数内,var和function也有声明提前的作用,如果不加var,会去找全局
在函数中,如果不使用var,都会变成全局变量,如果能找到,就会给全局变量赋值
定义形参,相当于在函数内声明了一个局部变量,如果没传值,不会找全局的,会报错
this
this表示的是函数执行的上下文对象,根据调用方式的不同,this指向不同的对象
当作为函数执行时,this永远指向window
当作为方法执行时,this指向的是被执行的对象
当在构造函数执行时,this指的新创建的对象
使用call和apply时,this为其制定的对象
构造函数
构造函数就是一个普通函数,在创建上和普通函数没有区别,在命名上,习惯首字母大写,在ES5以下的版本中,没有类的概念,使用同个构造函数创建的,将为同一类,这是js中的类
但构造函数和普通函数的调用方式不同,构造函数使用new关键字来调用,调用后将生成1个对象, 构造函数不用写retrun
new一个对象的过程:
0、创建构造函数
1、使用new调用构造函数。将立即创建一个对象,创建空间分给此对象栈内存中存变量名,堆内存中存具体的对象内容,并在栈内存内记录此堆内存的地址
2 将新建的对象设置为函数中的this(可以用this来创建属性和赋值),this此时指向堆内存中的对象空间
3、逐行执行构造函数中的代码,在堆内存中写入键值对。
4 结束函数,生成对象。
注意,只有用了new关键字,才会返回对象,否则只是执行函数
使用instanceof 可检查一个对象是否是一个类的实例 (实例 instanceof 构造函数)
所有对象都是object的后代
对于构造函数中的方法,如果方法放在构造函数内,每次实例化都将实例化一个方法,大量无用的占用内存
原型
每个函数,解析器都会向函数中填写一个属性prototype(显式原型对象),这个属性对应1个对象,即原型对象
如果函数作为普通函数调用,prototype没有作用
如果函数以构造函数的形式调用,其创建的对象均会有一个隐藏属性指向同样的prototype,即原型对象,在类的构造函数中,通过构造函数.prototype查看 在实例对象中,通过对象.proto(隐式原型对象) 来访问(函数也是个对象,其也有__proto__ ,但是和prototype内容一样)
原型对象相当于一个公共区域,所有的该类的实例的原型内存地址均一致。同类的实例均可访问这个对象,可向这个对象来添加属性,让所有实例访问同样的原型对象,其不会影响全局,且节省内存
添加方法 函数名.prototype.新属性/方法名
对象在调用方法时候,先在自己对象内查找,再去原型找。如果没有再去原型的原型中找,直到找到object对象的原型,如果也没有找到,则为undefined,一般只有2层原型,一层自身,一层object,这种一层层查找的方式,叫为原型链
类中的属性检查
使用in检查对象是否含有某个属性时候,如果原型有,也会返回true
可使用对象.hasOwnProperty(‘方法/属性’)来检查是否自身有
原型对象也有原型object的原型的原型为null
在直接打印对象时候,实际是调用toString()方法,如果希望输出时候不输出[object Object],可通过重写函数原型的toString方法来处理
构造函数:constructor prototype中的一个方法,指向构造函数的地址。即构造函数内的prototype指向其原型对象,而原型对象内的constructor指向构造函数,两边互相指向。比如前面截图中的例子里面的类声明部分的内容即被存在了constructor中。
JS垃圾回收机制GC
当一个对象没有任何变量或者属性对其引用时,我们将永远无法操作该对象,其将变为垃圾,需使用GC来进行清理
JS中有自动的垃圾回收,自动销毁,我们无法进行垃圾回收操作
如果我们需要丢弃对象,需要将其设置为null
对象分类
自定对象(用户自己创建的)、内建对象(String、Number等)、宿主对象(BOM、DOM)
函数的方法 call() apply()
都是函数的对象方法,通过函数对象来调用,当调用时,都会调用原本的函数。
不同的是,在调用时,可将1个对象作为第一个参数,这是this将会变为该参数的对象,这个将修改函数的this指向的内容
call方法时,可把实参放后面接着传进去
apply需要把剩下的实参作为数组封装传进去
arguments 实参数组
arguments为函数的隐含属性,其为实参的伪数组,有长度和索引,但是没有数组的方法
即时不定义形参,也可以用其调用
arguments.callee,表示当前正在执行的函数的对象