javascript-对象

雷薄
• 阅读 1052

6.1理解对象

创建方式:函数生成 和 字面量
例如:

   var a = new Object(); // new 构造函数方式
   var a = Object(); // 调用函数
   var a = {}; // 字面量

属性类型

(1)数据属性:[[configurable]](能否修改属性), [[enumerable]](能否通过for in 循环获取),[[writable]](能否修改),[[value]], 通过Object.defineProperty(obj, proper, properObj)方法修改默认属性
例如:

  var a = {
    name: 'jiang'
  };
  console.log(Object.getOwnPropertyDescriptor(a, 'name')); // {value: "jiang", writable: true, enumerable: true, configurable: true}
  Object.defineProperty(a, 'name', { 'writable': false});
  a.name = 'zhong';
  console.log(Object.getOwnPropertyDescriptor(a, 'name')); // {value: "jiang", writable: false, enumerable: true, configurable: true} // 值没有改变

(2)访问器属性:函数(getter(),setter), 特性([[Configuable]], [[Enumerable]], [[Get]], [[Set]])
例如:

var a = {
  name: 'jiang'
};
Object.defineProperty(a, 'sex', {
  get: function(){
    return 1;
  },
});
  a.name = 'zhong';
  console.log(a);
  console.log(a.sex);

(3)读取:Object.getOwnPropertyDescriptor()

6.2创建对象

工厂模式

定义:本义是将创建相同或相似对象的过程进行封装,只需调用封装后的函数就可以获取对象
解决的问题:类似的对象不用写重复的代码
带来的问题:创建的对象没有类型标识

  function factory(name){
 var o = {};
   0.name = name;
 o.action = function(){};
 return o;
  };// 在这里factory就是工厂模式的工厂
  var instance1 = facroty('san');
  var instance2 = facroty('si');

构造函数

定义:形如:function A(){};的函数, 通过new来进行实例化
解决的问题:同一个构造函数产生的实例类型项目(可以通过instanceOf鉴定), 实例间共享原型对象的属性
特点:构造函数内部的this指的是当前的实例对象
带来的问题:每个方法都属于不同的实例,就是没创建一个实例方法就会重新创建一遍

function Factory(name){
  this.name = name;
  this.action = function(){};
};
var instance1 = new Factory('san');
var instance2 = new Factory('si');
console.log(instance1 instanceof Factory); // true
console.log(instance2 instanceof Factory); // true

原型模式

定义:一个对象中属性和方法被所有实例所共享(共享实例都可以看成是这个复制品),这样的对象就是原型对象
解决的问题:构造函数的方法和属性在各个实例间是共享的

function Func(){};
Func.prototype.name = 'xiaotu';
Func.prototype.action = function(){
  console.log(this.name,'跑路');
};
var instance1 = new Func();
var instance2 = new Func();
instance1.action(); // xiaotu 跑路
instance2.action(); // xiaotu 跑路

特点:(1)通过new 构造函数产生实例对象,构造函数默认属性prototype指向实例对象的原型对象, 原型对象的默认的constructor(constructor属性被实例对象所共享)属性又指向构造函数, 实例对象通过[[ProtoType]]指向实例得原型对象

function Func(){};
console.log(Func.prototype); // {constructor: ƒ}
console.log(Func.prototype.constructor); // ƒ Func(){}
var instance1 = new Func(); // instance1可以访问原型的constructor
console.log(instance1.constructor) // ƒ Func(){}
console.log(instance1.__proto__) // {constructor: ƒ}
// 关系图(*代表指向目标)
              constructor
      *----------------------------\
 函数(Func) ----------------------* 原型对象(Func.prototype)
      \           (prototype)      *
       \                          /
        \ (new)         (_proto_)/(Object.getPrototypeOf(instance1))
         \                      /
          \                    /
           \                  /
            \                /
             \              /
            对象实例(instance1)

(2)实例对象与原型对象之间的对应关系可以通过isProtoTypeOf()来判断, 可以通过getProtoTypeOf()获取对象实例的原型对象

function Func(){};
var instance1 = new Func();
console.log(Func.prototype.isPrototypeOf(instance1)); // true
console.log(Object.getPrototypeOf(instance1)); // {constructor: ƒ}

(3)实例对象与原型对象的属性可以重复但不会覆盖,只是搜索时优先搜索实例对象的

function Func(){
  this.name = 'jiang';
};
Func.prototype.name = 'zhong';
var instance1 = new Func();
console.log(instance1.name); // jiang
delete instance1.name;
console.log(instance1.name); // zhong

(4)hasProprtyOf():判断对象实例中是否有此属性, in:判断对象实例和原型对象中是否由此属性, for - in 循环遍历包括原型和实例的属性, Object.keys() 返回所有实例的属性

function Func(){
};
Func.prototype.name = 'zhong';
var instance1 = new Func();
console.log(instance1.hasOwnProperty('name')); // false
console.log('name' in instance1); // true

(5)原型对象添加属性的方式:'.'(增量添加) '{}'(覆盖添加此时有默认的constructor指向Object)
带来的问题:如果原型对象的属性是引用类型的那么实例对象和原型对象的这个属性是同一个引用, 所以有了组合原型模式和构造函数,将引用属性定义在构造中就没这个问题了
:当通过实例去写值得时候如果实例不存在该属性则会去原型属性中查找,如果在原型中是引用类型的属性则对原型属性修改,如果是基本类型的则在实例中新建属性并赋值

function Func(){
  this.legs = ['left'];
};
Func.prototype.arms = ['right'];
var instance1 = new Func();
instance1.legs.push('right');
instance1.arms.push('left');
var instance2 = new Func();
console.log(instance2.legs); // ["left"]
console.log(instance2.arms); // ["right", "left"]
console.log(instance2.hasOwnProperty('arms')); // false
console.log(instance2.__proto__.hasOwnProperty('arms')); // true

组合原型模式和构造函数:原型模式负责定义实例共享的属性和方法, 构造函数定义每个实例特定的方法和属性

如上例(5)

6.3继承

只支持实现继承(相对于接口继承)

原型链

  定义:将一个(函数A)对象实例a赋值给某个函数B的原型B.prototype,那么B的实例b就拥有了a的属性,如果让A的原型的值等于另一个实例,a也拥有了其他对象的值, 如此形成了原型链
  解决的问题:让对象之间实现了继承
function SuperFunc(){
  this.name = 'big-jiang';
};
function SubFunc(){
  this.name = 'small-jiang';
};
var superFunc = new SuperFunc();
SubFunc.prototype = superFunc;
var subFunc = new SubFunc();
console.log(subFunc.name); // 'small-jiang'
console.log(subFunc.__proto__.name); // 'big-jiang'
SuperFunc.prototype = new ...  // 继续继承成链
  特点:
     (1)所有对象都继承了Object, 可以通过对象原型的原型(最后一层原型)的constructor是否指向Object的原型去判断
function SuperFunc(){
  this.name = 'big-jiang';
};
function SubFunc(){
  this.name = 'small-jiang';
};
console.log(SuperFunc.prototype.constructor == Object); // false 应是SuperFunc
console.log(SuperFunc.prototype.__proto__.constructor == Object); // true
var superFunc = new SuperFunc();
SubFunc.prototype = superFunc;
console.log(SubFunc.prototype.constructor == SubFunc); // false 应是SuperFunc
console.log(SubFunc.prototype.constructor == SuperFunc); // true
console.log(SubFunc.prototype.__proto__.constructor == SuperFunc); // true
console.log(SubFunc.prototype.__proto__.__proto__.constructor == Object); // true
     (2)确定某原型是不是对应某实例间可以通过instanceOf和isPrototypeOf()
function SuperFunc(){
  this.name = 'big-jiang';
};
function SubFunc(){
  this.name = 'small-jiang';
};
var superFunc = new SuperFunc();
SubFunc.prototype = superFunc;
var subFunc = new SubFunc();
console.log(subFunc instanceof SubFunc); // true
console.log(subFunc instanceof SuperFunc); // true
   带来的问题:父级的实例变成了子级的原型,父级的属性是引用类型的话就会带来所有实例共享的问题,不能向父级构造函数传递参数
function SuperFunc(){
  this.arms = ['left'];
};
function SubFunc(){
};
var superFunc = new SuperFunc();
SubFunc.prototype = superFunc;
var subFunc1 = new SubFunc();
subFunc1.arms.push('right');
var subFunc2 = new SubFunc();
console.log(subFunc2.arms); // ["left", "right"]

借用构造函数

   定义:在子函数中通过apply或者call将当前作用域传给父函数来实现继承
   解决的问题:这样就不会有原型带来的共享引用属性的问题, 也可以在apply或者call中传递参数
function SuperFunc(name){
  this.name = name;
};
function SubFunc(){
  this.name = 'zhong';
  SuperFunc.call(this, 'jiang');
};
var subFunc = new SubFunc();
console.log(subFunc.name); // jiang
   带来的问题:复用性差,父级原型中的属性方法,自己都不能获取到

组合继承

   定义:将借用构造函数和作用域链两种方式结合起来使用
   解决的问题:将前两种继承方式的优点结合起来, 缺点可以选择性去避免
function SuperFunc(name){
  this.name = name;
  this.arms = ['left'];
};
function SubFunc(){
  SuperFunc.call(this, 'jiang');
};
var superFunc = new SuperFunc();
SubFunc.prototype = superFunc;
var subFunc = new SubFunc();
subFunc.arms.push('right');
var subFunc2 = new SubFunc();
console.log(subFunc2.arms); // 'left'
点赞
收藏
评论区
推荐文章
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Chase620 Chase620
4年前
Promise从入门到拿Offer之手写Promise
1、Promise构造函数的实现Promise构造函数用来声明示例对象,需要传入一个执行器函数。其中包括resolve函数和reject函数,以及几个重要的属性:状态属性、结果属性和回调函数队列。构造函数的基本框架resolve函数用于异步处理成功后调用的函数。其中包括验证对象状态修改次数,修改promise实例对象状态,异步调用成功的回调函数
Stella981 Stella981
4年前
JavaScript 正则表达式上——基本语法
定义JavaScript种正则表达式有两种定义方式,定义一个匹配类似<%XXX%的字符串1\.构造函数varregnewRegExp('<%\^%\%','g');2\.字面量varreg/<%\^%\%/g;g:global,全文搜索,默认搜索到第一个结果接停止
Stella981 Stella981
4年前
IOS label和button
//创建UILabel函数(void)creatUILabel{//定义并创建一个UILabel对象UILabellabelUILabelallocinit;//文字赋值,字符串对象,设定字体大小,颜色,阴影,阴影偏移量,对齐方式,显示行数(
Wesley13 Wesley13
4年前
JS中正则表达式
正则表达式的定义js中的正则表达式使用RegExp对象表示,两种创建正则表达式对象的方法直接量定义将表达式包含在斜杠之间varpattern/js/;构造函数定义:使用RegExp()构造函数定义varpatternnewRegExp('js');
Wesley13 Wesley13
4年前
C++中构造函数和析构函数
构造函数定义它是一种特殊的方法。主要用来在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。另外,一个类可以有多个构造函数,我们可以根据其参数个数的不同或参数类型的不同来区分它们(这就是构造函数的重载)特点1.构造函数的命名必须和类名完全相同;2.构造函数的功能主要用于在类的对象创建时定义
Stella981 Stella981
4年前
GitHub标星13.2k,JavaScript基础知识之变量详解,前端入门必看
一、字面量:数字和字符串“字面量”即常量,是固定值,不可改变。看见什么,它就是什么。字面量有3种:数字字符串布尔字面量(1)数值的字面量非常简单,写上去就行,不需要任何的符号。例如:alert(886);//886是数字,所以不需要加
Stella981 Stella981
4年前
JavaScript(js)字面量,函数写法
JavaScript字面量在编程语言中,一般固定值称为字面量,如3.14。数字(Number)字面量可以是整数或者是小数,或者是科学计数(e)。3.141001123e5字符串(String)字面量可以使用单引号或双引号:"JohnDoe"'JohnDoe'表达式字面量用于计算:
Wesley13 Wesley13
4年前
JS创建对象模式7种方法详解
创建对象的几种模式虽然Object构造函数或者字面量,都可以用来创建对象,但这些方式有明显的缺点:使用同一个接口创建很多对象,会产生大量的代码,于是,工厂模式诞生了1工厂模式工厂模式是广为人知的设计模式,抽象了创建具体对象的过程。在ES6的Class创建类之前,是无法创建类的,开发人员就发明了一种函数,用函数来封
小万哥 小万哥
2年前
Java 构造函数与修饰符详解:初始化对象与控制权限
Java构造函数Java构造函数是一种特殊的类方法,用于在创建对象时初始化对象的属性。它与类名相同,并且没有返回值类型。构造函数的作用:为对象的属性设置初始值执行必要的初始化操作提供创建对象的多种方式构造函数的类型:默认构造函数:无参数的构造函数,如果用户
小万哥 小万哥
1年前
C++ 构造函数实战指南:默认构造、带参数构造、拷贝构造与移动构造
C构造函数构造函数是C中一种特殊的成员函数,当创建类对象时自动调用。它用于初始化对象的状态,例如为属性分配初始值。构造函数与类同名,且没有返回值类型。构造函数类型C支持多种类型的构造函数,用于满足不同的初始化需求:默认构造函数:不带参数的构造函