对象创建方法
- 对象字面量 {}
- 构造函数
1)系统自带的构造函数 new Object()
2)自定义 大驼峰式命名
构造函数三段式 当new的时候
- 在函数内部最前面隐式加上 this = {}
- 执行 this.XXX = XXX
- 最后return , 返回this
但是如果要自己return某个值的话,不能返回原始值
对象操作 增 删(delete) 改 查
包装类
new Number()
new String()
new Boolean()
通过以上构造函数创建出来的number,string,boolean就是对象类型的number,string,boolean
对象上面就会有属性和方法
var str = \'abcd\'
str.length = 4
//以上是 new String(\'abcd\').length = 4 然后 delete
//所以不报错是因为包装类重新创建了一个字符串对象,然后又删掉了这个对象
console.log(str.length) //4
原型
例如构造函数Fun,其构造的对象fun
- Fun.prototype = {} -- 就是构造函数Fun构造出来的对象(如fun)的原型(祖先)
- 通过该构造函数构造出来的对象都可以继承原型的方法和属性
- 原型也是对象
function Fun() {}
var fun = new Fun()
利用原型的特点,可以提取公共属性
Bar.prototype.height = 188;
function Bar(level){
this.level = level
}
var bar1 = new Bar(2)
var bar2 = new Bar(6)
//bar1 bar2 都可以继承level属性和原型上的height
对象只能操作自己本身的属性,对于原型上的属性只有原型本身可以操作
constructor会返回构造对象的构造函数 , 但是该属性可以人为修改
function Foo() {}
var foo = new Foo()
foo.constructor // Foo 返回构造该对象的 构造函数
// 可以打印Foo.prototype会发现它上面有一个系统给的隐式属性constructor
__proto__
1.每一个构造函数创建的对象上面存的原型,之所以会沿着原型查找属性和方法,其实就是__proto__的一种连接,
2.可修改
3.new的时候第一步 var this = { __proto__ : Foo.prototype }
Foo.prototype.name = \'sune\'
function Foo() {
//var this = { __proto__ : Foo.prototype }
}
var foo = new Foo()
Foo.prototype.name = \'cosen\'
foo.name //cosen
// __proto__引用地址Foo.prototype没变, 所以修改Foo.prototype属性,__proto__也会改变
Foo.prototype.name = \'sune\'
function Foo() {}
var foo = new Foo()
Foo.prototype = {
name : \'cosen\'
}
原型链
原型链的终端是Object.prototype ,Object.prototype.proto = null
原型链增 删 改 查,仅对象可以改自己的,并不能改原型上面的
Object.create(原型) Object或null
Object.create(null) //没有__proto_ 原型
- 只有undefined和null没有toString()方法,数字,布尔值,字符串可以通过包装类来访问toString
- 包装类上面有原型 Number.prototype.proto = Object.prototype
- 并且原型上面有toString方法,该方法是重写的,它覆盖了原型链终端的toString方法
call apply bind 都是用来改变this指向,区别传参形式不同,call和apply是立即执行,bind返回原函数,需再次执行
让对象调用函数,对象想要用到函数的属性或方法
函数.call(对象,参数1,参数2,...)
函数.apply(对象,[参数1,参数2,...])
函数.bind(对象,参数1,参数2,...)
//将构造函数里面的this指向obj ,obj 就可以借用函数的方法或属性
function Bar(name){
// this = obj
//obj.name = name
this.name = name
}
var obj = {}
Bar.call(obj,\'sune\')
obj.name // obj本身没有name属性,这样子通过call就可以借用函数Bar的属性,实现属性赋值的功能
关于包装类
//让对象调用函数 ,Object上面的toSting方法会有如下返回值
Object.prototype.toString.call(123) // "[object,Number]"
Object.prototype.toString.call("abc") // "[object,String]"
Object.prototype.toString.call(true) // "[object,Boolean]"
Object.prototype.toString.call([]) // "[object,Array]"
//所以后来这些包装类的构造函数都重写了toString方法,所以在原型链上找时会就近用自己的toString
Object.prototype.toString
`Number.prototype.__proto__ = Object.prototype`
Array.prototype.toString
Number.prototype.toString
String.prototype.toString
Boolean.prototype.toString
var test = Object.create(null)
document.write(test) // 报错 无原型 无toString方法
var test = {}
document.write(test) // [object Object]
继承
- 原型链继承
继承过多无用的属性和方法 - 借用构造函数 call apply
不能继承构造函数的原型
每次都会多执行一个函数,即借用的函数 - 共享原型
不能随意修改原型上面的属性,引用地址相同 - 圣杯模式,最好的继承实现方式
//方法1 常规操作
function inherit(Target , Origin){
function F(){}
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.super = Origin.prototype;
}
//方法2 闭包实现变量私有化的高端写法
var inherit = (function(){
var F = function(){}
return function(Target , Origin){
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constructor = Target;
Target.prototype.super = Origin.prototype;
}
}())
对象枚举,遍历
- for...in 遍历对象属性,包括原型上面的属性
- hasOwnProperty 判断属性是不是属于对象自身的,可以过滤原型上面的属性
- in 能不能在对象上面访问到属性,不能过滤原型上面的属性,只关注可不可以通过对象拿到
- instanceof // A instanceof B 看A的原型上面有没有B的原型
Object.prototype.name = \'cosen\'
var obj = {
name : \'sune\' ,
__proto__ : {
lastName : \'sun\'
}
}
//for in 会拿到原型上面的属性
// hasOwnProperty 是用来检验是不是对象自身的属性而不是原型上面的属性
for(var key in obj){
console.log(key) // name lastName
if(!obj.hasOwnProperty(key)){
console.log(obj[key]) // sun
}
\'lastName\' in obj //true
}
// A instanceof B 看A的原型上面有没有B的原型
function Bar(){}
var bar = new Bar()
bar intanceof Bar //true
bar intanceof Object //true
bar intanceof obj //false
//如何区分一个变量是对象还是数组
var obj = {};
var arr = [];
arr instanceof Array //true
obj instanceof Object //true
Object.prototype.toString.call(arr) //\'[object , Array]\'
Object.prototype.toString.call(obj) //\'[object , Object]\'
arr.constructor // ƒ Array() { [native code] }
obj.constructor // ƒ Object() { [native code] }