目录
对象
JavaScript 对象是拥有属性和方法的数据。
对象也是一个变量,但对象可以包含多个值(多个变量)。
7.1 对象基础
7.1.1 对象创建
1. 对象字面量
2. 工厂模式
为了解决上述问题,人们开始使用工厂模式。该模式抽象了创建具体对象的过程,用函数来封装以特定接口创建对象的细节
3. 构造函数模式
可以通过创建自定义的构造函数,来定义自定义对象类型的属性和方法。创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型,而这正是构造函数模式胜过工厂模式的地方。该模式没有显式地创建对象,直接将属性和方法赋给了this对象,且没有return语句
使用构造函数的主要问题是每个方法都要在每个实例上重新创建一遍。
4. new创建
new后面跟一个函数表示创建对象; 这里的函数是构造函数(constructor)。(任何对象都有构造函数,任何对象都是函数创建出来的)
js是一个基于面向对象的单线程的脚本语言
只要是函数,就可以new. 任何对象都有构造函数(任何对象都是函数创建出来的)
new fn() //new关键字后面跟函数,是一个表达式(运算符)创建对象的运算,整个表达式一定会得到一个对象
//1、创建一个空对象
//2、运行构造函数,让内部的this指向创建的对象(用创建的空对象去调用构造函数)
//3、整个表达式的结果看函数的返回值(无论函数是否有return,最后一定会返回一个对象)
//3.1返回值是引用数据(函数、数组...),那就它
//3.2返回值不是引用数据,那就是这个运行完毕之后的创建的那个对象
new后面一般跟一个函数,new会创建对象,而且会去调用这个函数
new fn //创建对象,然后调用函数,不传参,new无参
new fn() //创建对象。然后调用函数,并传参数,new带参
console.log(name) //window.name = "",结果为 ""
5. Object.create()创建
Object.create()的参数只能是对象或null;
用于创建一个新对象,参数是这个对象的原型
7.1.2 对象方法
1. valueOf()
valueOf()方法返回当前对象原始值
object 引用是任何内部 JavaScript 对象,将通过不同的方式为每个内部 JavaScript 对象定义 valueOf 方法。
2. toString()
toString()方法返回当前对象对应的字符串形式
toString 方法是一个所有内置的 JavaScript 对象的成员。 它的行为取决于对象的类型:
附注:valueOf偏向于运算,toString偏向于显示。
1、 在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
2、 在有运算操作符的情况下,valueOf的优先级高于toString。
7.1.3 对象属性
对象的属性名不可以重复,一般后写的会覆盖前面写的
属性的查询和设置: 点(.)和中括号([])
删除属性 : delete运算符可以删除对象属性 (只能删除自有属性,不能删除继承属性)。delete删除成功 或 删除不存在的属性 或 没有副作用时,返回true。
- 检测属性
(a) in:检查一个属性是否属于某个对象,包括继承来的属性;
(b) hasOwnProperty():检查一个属性是否属于某个对象自有属性,不包括继承来的属性;
(c) propertyIsEnumerable()是hasOwnProperty()的增强版:
检查一个属性是否属于某个对象自有属性,不包括继承来的属性,且该属性可枚举;
- 枚举属性
for/in循环遍历对象中所有可枚举属性!!把属性名称赋值给循环变量;
for/in配合使用hasOwnProperty()可得到对象中可枚举的自有属性:propertyIsEnumerable()
- 存取器属性getter和setter
属性值可以由一个或两个方法替代,这两个方法就是getter和setter
(a) 由getter和setter定义的属性,称为“存取器属性”;
(b) 一般的只有一个值的属性称为“数据属性”;
与存取器属性同名的函数定义没有使用function关键字,而是使用get或set,也没有使用冒号将属性名和函数体分开,但函数体的结束和下一个方法之间有逗号隔开。
(c) 查询存取器属性的值,用getter;拥有getter则该属性可读;
(d) 设置存取器属性的值,用setter;拥有setter则该属性可写;
7.1.4 序列化对象
序列化对象是指将对象的状态转成字符串,也可以将字符串还原为对象;
(a) 转成字符串:JSON.stringify();
(b) 还原为对象:JSON.parse();
7.2 this机制
this是JavaScript语言中关键字之一,它的特殊在于它自动定义于每一个函数域内。
7.2.1 this的误解
很多编程语言中都有this的机制,惯性思维把其它语言里对它的理解带到了JavaScript中。同时,由于this这个单词的理解导致了我们产生了对它各种各样的误解。
1. this引用function自身--误解
在函数里引用函数可以达到递归和给函数属性赋值的效果。而这在很多应用场景下显得非常有用。所以,很多人都误以为this就是指引function本身。
注:函数变量不等于函数属性。
【this,一个特殊的对象】
1、全局作用域里的this: this-->window
2、函数里的this,全局下直接调用函数: this-->window
3、函数里的this,new 操作调用函数:this-->实例对象
4、函数里的this,函数写在对象的属性值里,通过对象属性调用函数:this-->该对象
//总而言之,谁调用的函数,函数里的this 就指向谁!!
5、函数里的this,使用call/apply 调用函数并传参,可以改变函数运行时this 的指向:this-->指定对象
2. this引用的是function的词法作用域--误解
7.2.2 this运用规则
this到底绑定或者引用的是哪个对象环境决定于函数被调用的地方。而函数的调用有不同的方式,在不同的方式中调用决定this引用的是哪个对象。
1. 默认绑定全局变量
这条规则是最常见的,也是默认的。当函数被单独定义和调用的时候,应用的规则就是绑定全局变量。
2. 隐式绑定
隐式调用的意思是,函数调用时拥有一个上下文对象,就好像这个函数是属于该对象的一样。
3.显式绑定
bind()\apply()\call()函数,它接收的第一个参数即是上下文对象并将其赋给this。
7.2.3 this总结
总结:this的调用者
方法一:fn() //window
obj.fn() //obj
obj.xx.xx2() //obj.xx
(function(){})() //window
fn()() //window
fn()[1]() //fn()返回的数组
方法二:只需要看离this最近的function(嵌套级别的)这个单词的调用者
7.2.4 注意点
函数:
函数可以不写函数名(定义函数可以不用给名字,声明的函数要写名字)
匿名函数:小括号 它是一种运算符 指向结果 它可以让函数不起名字
这种匿名函数的自调用的写法,它的调用者是window
(function () {
console.log(123)
console.log(this) //结果为window
})(); //前面的括号是指 指向数据,后面的括号是调用
var a=b=c; //a是最后赋值(引用)的,但是a的引用声明是一开始就有了
var a.x=b; //这个是将a里面的成员去等于bthis基本上就代表的是对象, 在极其少的时候this不是对象(call apply bind)
this=200; //这样的写法是错误的
js数据类型只有两种: 基本数据、引用数据(object、function)
函数是js数据类型的引用数据,函数可以保存数据
7.3 原型对象
1. 函数的原型对象
在JavaScript中,我们创建一个函数A,那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象(即:prototype的属性的值是这个对象 )。这个对象B就称作是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性constructor指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。
2. 使用构造函数创建对象
当把一个函数作为构造函数 使用new创建对象的时候,那么这个对象就会存在一个默认的不可见的属性,来指向了构造函数的原型对象。这个不可见的属性我们一般用[[prototype]]来表示,只是这个属性没有办法直接访问到。
3.小小知识点
构造函数有两类:
自定义函数
官方提供的函数: Function String Number Bloolean Object Array Date Math
语法糖:代码有多种写法时,简便的写法就是语法糖
(obj.age就是语法糖,它的原本是:obj["age"]。 autofocus,selected都是)
语法糖: 对象直接量:var obj2={}
var arr1 = new Array()
console.log(arr1.__proto__.__proto__.__proto__) //null
自定义构造函数的原型对象也是一个自定义构造函数创建的对象
Object 是一个函数,typeof检测出来是function
Function 也是一个函数,typeof检测出来是function。function是一个关键字
函数有三种写法
1、声明式:写一个函数,运行脚本时,系统预编译时帮我们创建这个函数对象
2、定义式:创建函数的语法糖,直接生成一个函数数据(对象)被标识引用
var a = function () {}
3、标准的创建一个函数对象:
var f1 = new Function("var a=20;console.log(a)") //里面是字符串,下面代码执行时,也会执行
f1() //20
var f1=new Function("var a=20;console.log(a)")
上面一行代码和下面代码一样
var f1 = function () {
var a = 20;
console.log(a)
}
f1.__proto__ 返回的是native code
Function.prototype //所有的函数对象的原型对象,不管是声明式、定义式,还是标准创建一个函数,不管是叫什么名字,所有函数的原型对象都是它
对象的成员操作
给对象存值,如果自己有就修改,没有就添加,不会对原型对象里的内容进行修改和添加,原型对里的东西只能取值
取一个对象的属性值 自己没有就取原型对象的 也没有就取原型的原型 直到null都没有 就取出undfined
如果给一个对象存值,没有这个属性 就直接创建这个属性
如果给一个对象存值,有这个属性,更新
原型对象的操作
原型对象虽然不可以通过=等操作来给原型对象进行增加修改更新等,但是可以通过.语法来进行增加
fn.prototype.x=20 //给fn的原型对象里添加x属性
fn.prototype={x:20} //直接将fn的原型对象增加了另一个空间--创建了一个对象系统内置构造函数的原型属性是不可以修改的 可以操作这个对象的属性
Array.prototype.h=200//所有的数组都有h属性=>200
Array.prototype={name:"karen"}//这个代码是直接将原型对象的类型都改了,不会报错 但是不会生效==>跳过编译(静默)
7.4 继承-原型链
每一个对象都从原型继承属性,直到null结束。
所有的内置构造函数都有一个继承自Object.prototype的原型
一、构造函数、原型和实例的关系 a,构造函数都有一个属性prototype,这个属性是一个对象,是Object的实例; b,原型对象prototype里有一个constructor属性,该属性指向原型对象所属的构造函数; c,实例对象都有一个__proto__属性,该属性指向构造函数的原型对象; obj.__proto__===Object.prototype 二、prototype与_proto_的关系 a,prototype是构造函数的属性; b,__proto__是实例对象的属性; c,两者都指向同一个对象;
原型链作为继承的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
每个构造函数都有一个原型对象prototype,原型对象都包含一个指向构造函数的指针constructor,而实例都包含一个指向原型对象的内部指针 [[prototype]]。
如果让原型对象等于另一个类型的实例,那么原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。