对象
对象
属性
var person={
'name':'zhangsan',
age:18,
5:true
}
对象属性访问
点表示法
属性不能包含空格等 导致语法错误的字符,或者是关键字或保留字或数字
obj={
name:'张三',
age:21,
5:23,
'var t':3 //字符串才允许有空格
}
p='name'
console.log(obj.name);;//张三
console.log(obj.5);//报错
console.log(obj.var t);//报错
console.log(obj.'var t');//报错
console.log(obj.p);//und
方括号表示法
属性可以是变量,包含空格,关键字或保留字
obj={
name:'张三',
age:21,
5:23,
'var t':3 //字符串才允许有空格
}
p='name'
console.log(obj[5]);//23
console.log(obj['5']);//23
console.log(obj[var t]);//报错
console.log(obj['var t']);//3
console.log(obj[p])//'张三'
对象访问器
本质也是函数 只不过 使用函数名不需要() 就会调用函数
当访问器与属性重名时
访问器声明在下方则会覆盖属性
属性在下方则会覆盖访问器
get关键词
var ob={
name:'123',
age:2,
def:function(){
return 1
},
get getName(){
return this.name
}
}
console.log(ob.def()) //需要()调用函数
console.log(ob.getName);// 不需要
var ob={
name:'123',
age:2,
def:function(){
return def() //这样会发生递归
},
get name(){//与属性重名
return this.name// 这样会发生递归 而不是返回属性name
}
}
console.log(ob.def());//调用对象函数
console.log(ob.name);//调用访问器
访问器与属性同名时 声明在下方的优先级更高
var ob={
name:'123',
age:2,
get name(){
return 2
}
}
console.log(ob.name) // 调用了访问器 输出2
set关键词
var ob={
age:2,
name:'123',
get getName(){
return this.name
},
set setName(value){
this.name=value
} ,
def:function(val){
this.name=val;
}
}
ob.def('zhangsan');//函数使用方法
ob.setName='张三' //set使用方法
console.log(ob.name);
属性defineProperty()
数据属性

writable
var person={
name:'zhangsan'
}
Object.defineProperty(person,'name',{
writable:false,//name属性不可修改
value:'lisi'
})
console.log(person.name);//lisi
person.name='wangwu';
console.log(person.name);//lisi
configurable
var person={
name:'zhangsan',
age:13,
}
Object.defineProperty(person,'name',{
configurable:false,//name属性不可配置
value:'lisi'
})
console.log(person);
delete person.name;//无法删除name属性
delete person.age;//成功删除age属性
console.log(person);//{name:'lisi'}
Object.defineProperty(person,'name',{
configurable:true,//报错 一旦被定义为不可配置那么就不能再变回可配置了
value:'wangwu'
})
enumerable
var person={
name:'zhangsan',
age:13,
phone:1329092285
}
Object.defineProperty(person,'name',{
enumerable:false,//name属性不可在forin时遍历key找到
value:'lisi'//直接给属性赋值
})
for (const key in person) {
if (Object.hasOwnProperty.call(person, key)) {
const element = person[key];
console.log(key,':',element);
}
}
//输出:
//age: 13
//phone:1329092285
访问器属性
Get 和 Set
var person={
_name:'zhangsan',//_符号 表示属性只能通过 对象方法(或对象访问器)访问的属性
_age:13,
}
Object.defineProperty(person,'name',{
get:function(){
return '姓名:'+this._name;
},
set:function(){
this._age=0;
}
})
console.log(person.name);//姓名:zhangsna
person.name='lisi'//触发了set 修改了_age的值
console.log(person);//{ _name: 'zhangsan', _age: 0 }
constructor属性
实例的一个属性,可以获取实例的构造函数引用。
function Person(name,age,job){
this.nam=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
var p1=new Person('zhangsan',18,'a');
console.log(p1.constructor);//[Function: Person]
constructor获得构造函数的引用甚至可以调用
var p2= new p1.constructor('lisi',18,'b');
console.log(p2);
//p2={
// nam: 'lisi',
// age: 18,
// job: 'b',
// sayName: [Function (anonymous)]
//}
构造函数
构造函数创建实例过程
- 创建一个新对象; (如果有new关键词)
- 将构造函数的作用域指向新对象;(this就指向了新对象)
- 执行构造函数中的代码;(正常按照函数ao顺序执行)
- 返回新的对象;
关于 new 关键词
new 关键字会进行如下的操作:
- 创建一个空的简单JavaScript对象(即{});
- 为步骤1新创建的对象添加属性proto,将该属性链接至构造函数的原型对象 ;
- 将步骤1新创建的对象作为this的上下文 ;
- 如果该函数没有返回对象,则返回this。
构造函数的使用
function Person(name,age,job){
this.nam=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
var p1=new Person('zhangsan',18,'a');//函数作用域 new对象
console.log(p1);
Person('lisi',18,'c');//函数作用域 window/global
console.log(globalThis);
globalThis.sayName();//'lisi'
//更具环境给window或global 添加了name,age,job...属性
函数内的函数
函数是一个对象,因为使用了new关键词,每个对象内声明的函数属于不同的作用域,那么也就是不同的对象。
弊端:重复完全相同功能的函数
function Person(name,age,job){
this.nam=name;
this.age=age;
this.job=job;
this.sayName=function(){
console.log(this.name);
}
}
var p1=new Person();
var p2=new Person();
console.log(p1.sayName==p2.sayName);//false
解决方法:
在全局创造函数 sayName , 对象内属性去引用全局的 sayName函数。
function Person(name,age,job){
this.nam=name;
this.age=age;
this.job=job;
this.sayName=sayName;
}
function sayName() {
console.log(this.name);
}
var p1=new Person();
var p2=new Person();
console.log(p1.sayName==p2.sayName);//true
弊端:全局作用域会有很多对象的函数,乱
原型模式
原型对象
在创建函数的同时会创建一个对象(原型对象),函数再创建一个prototype属性指向这个原型对象。
原型对象的属性:
- constructor (一个指针:指向函数。)
- 其他属性和方法 继承Object
理解:
原型对象相当于静态代码块,每个实例都会拥有(继承)它的属性和方法。
访问实例的属性时 :
- 先搜索对象实例本身 是否拥有该属性,有的话直接返回属性值
- 对象实例没有该属性 再搜索__proto__指向的原型对象,如果有的话再返回值
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype.say=function () {
console.log('hello');
}
Person.prototype.sex='female'
Person.prototype.name='wangwu'
var p1=new Person('zhagnsan',18,'a');
p1.say(); //'hello' p1对象实例没有say() 然后去搜索它的 原型对象 找到方法say()
console.log(p1.sex);//'female' p1实例中没有sex属性,去搜索原型对象的sex属性 并返回值
console.log(p1.name);//'zhangsan' p1实例中有name属性 直接返回 不再去搜索原型对象
从原型对象继承来的函数方法 是同一个 (因为和原型对象绑定的构造函数只有一个,作用域也就只有一个)
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
Person.prototype.say=function () {
console.log('hello');
}
Person.prototype.sex='female'
Person.prototype.name='wangwu'
var p1=new Person('zhagnsan',18,'a');
var p2=new Person('lisi',18,'c');
console.log(p1.say==p2.say);//true
prototype和constructor
实例和函数 都有prototype属性 ,指向原型对象
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
var p1=new Person();
Person.prototype.name='123'
console.log(Person.prototype);//原型对象{ name: '123' }
console.log(p1.__proto__);//原型对象{ name: '123' }
实例和原型对象 都有constructor属性,指向构造函数
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
}
var p1=new Person();
Person.prototype.name='123'
console.log(Person.prototype.constructor);//[Function: Person]
console.log(p1.constructor);//[Function: Person]
用途:prototype和constructor属性能使 函数和原型对象 彼此找到对方
屏蔽性
访问属性的过程是一个搜索的过程,从当前语句this开始向上搜索,一旦访问到属性就停止。
使用父类的方法时可以理解为单纯的借用代码,不用考虑父类方法所在的this域,实际环境仍然是调用对象所在域
实例1: 直接访问属性
function Person(name) {
this.name=name
}
var p=new Person("张三")
Person.prototype.age=18;
访问属性时 属性重名 对象实例属性优先
p.age=20;
console.log(p.age);//20
就算对象实例属性值为null也优先
p.age=null;
console.log(p.age);//null
只能使用delete操作符才能完全删除实例属性,然后继承原型对象的属性
p.age=20;
delete p.age
console.log(p.age);//18
实例2:调用父类方法时,访问子父类重名属性
function SuperType() {
this.property=456
}
SuperType.prototype.getSuperValue=function(){
return this.property
}
function SubType() {
this.property=123;
}
let superins = new SuperType();
SubType.prototype=superins;
let ins=new SubType();
console.log(ins.getSuperValue());//123
console.log(superins.getSuperValue());//456
//使用父类的父类getSuperValue()方法访问重名属性时
//从最底层开始搜索(调用函数的this域开始向上搜索)
hasOwnProperty
hasOwnProperty(v: PropertyKey): boolean; 判断属性是否在对象实例中
- Determines whether an object exists in another object's prototype chain.
- @param v Another object whose prototype chain is to be checked.
function Person(name){
this.name=name
}
Person.prototype.sex='0'
let p=new Person("zhangsan");
p.age=13;
//判断是否是实例的属性
console.log(p.hasOwnProperty('name'))//true
console.log(p.hasOwnProperty('age'))//true
console.log(p.hasOwnProperty('sex'))//false
获取对象属性
- for in
- Object.keys()
- Object,getOwnPropertyNames()
原型对象默认继承Object的原型对象
-
原型对象的__proto__指向Object的prototype
注意继承的是Object的原型对象而不是Object的实例对象也不是Object的构造函数
function p1() {
this.age=3
}
console.log(p1.prototype.__proto__==Object.prototype);//true
console.log(p1.prototype.__proto__==Object);//false
console.log(p1.prototype.__proto__==new Object());//false
- 多继承的原型链
function p1() {
}
function p2() {
}
p2.prototype.name='123'
p1.prototype=new p2()
a=new p1()
g=new p2()
console.log(p1.prototype.__proto__==Object.prototype);//false 左=p2的原型对象
console.log(p1.prototype.__proto__.__proto__==Object.prototype);//true 左=Object的原型对象
//p1.prototype -----> p1的原型对象是p2实例对象
//p1.prototype.__proto__ ------> p1的原型对象的原型对象----> p2的实例对象的原型对象 ----->p2的原型对象
//p1.prototype.__proto__.__proto__ -------> p2的原型对象的原型对象(默认值,未经修改)-----> Object的原型对象
- 验证原型对象默认会继承Object的原型对象
原型对象的__proto__属性默认值为 Object.prototype
所以所有引用对象默认会继承Object原型对象的所有方法
function p1() {
}
let a=new p1()
console.log(a.__proto__.__proto__==Object.prototype)//true
//原型对象的_proto_属性默认值为 Object.prototype
console.log(a.toString);//function
p1.prototype.__proto__=null//修改原型对象的__proto__默认值
console.log(a.toString);//null 不再继承Object j

浙公网安备 33010602011771号