当前位置: 首页 > news >正文

深圳制作手机网站高端网站建设公司排行

深圳制作手机网站,高端网站建设公司排行,学网站建设有前途吗,室内设计学校大专原型与继承 在 JavaScript 中,对象有一个特殊的隐藏属性 [[Prototype]](如规范中所命名的),它要么为 null,要么就是对另一个对象的引用。该对象被称为“原型。 当我们从 object 中读取一个缺失的属性时,Jav…

原型与继承

在 JavaScript 中,对象有一个特殊的隐藏属性 [[Prototype]](如规范中所命名的),它要么为 null,要么就是对另一个对象的引用。该对象被称为“原型。

当我们从 object 中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。在编程中,这被称为“原型继承”。

'use strict';const user = {name: 'user',age: 18
}
const admin = {__proto__: user,  // __proto__ 的值可以是对象,也可以是 null。而其他的类型都会被忽略。一个对象只能有一个 [[Prototype]]。一个对象不能从其他两个对象获得继承。name: 'admin',
}
console.log(admin.name);   // admin
console.log(admin.age);  // 18console.log(admin.__proto__);  // { name: 'user', age: 18 }
console.log(admin.__proto__.__proto__);  // [Object: null prototype] {}
console.log(admin.__proto__.__proto__.__proto__);  // null
// 获取对象所有的属性名, 包括不可迭代的属性
console.log(Object.getOwnPropertyNames(admin.__proto__.__proto__));
/* 
['constructor','__defineGetter__','__defineSetter__','hasOwnProperty','__lookupGetter__','__lookupSetter__','isPrototypeOf','propertyIsEnumerable','toString','valueOf','__proto__','toLocaleString'
]
*/
// 只返回自己的 key
console.log(Object.keys(admin));  // [ 'name' ]
// for..in 会遍历自己以及继承的键
for(let key in admin) console.log(key);  // name age
// 方法 obj.hasOwnProperty(key):如果 obj 具有自己的(非继承的)名为 key 的属性,则返回 true。
console.log(admin.hasOwnProperty("name"));  // true
console.log(admin.hasOwnProperty("age"));  // false
  • __proto__[[Prototype]] 的因历史原因而留下来的 getter/setter

  • 初学者常犯一个普遍的错误,就是不知道 __proto__[[Prototype]] 的区别。

  • 请注意,__proto__ 与内部的 [[Prototype]] 不一样__proto__[[Prototype]] 的 getter/setter。稍后,我们将看到在什么情况下理解它们很重要,在建立对 JavaScript 语言的理解时,让我们牢记这一点。

  • __proto__ 属性有点过时了。它的存在是出于历史的原因,现代编程语言建议我们应该使用函数 Object.getPrototypeOf/Object.setPrototypeOf 来取代 __proto__ 去 get/set 原型。稍后我们将介绍这些函数。

  • 根据规范,__proto__ 必须仅受浏览器环境的支持。但实际上,包括服务端在内的所有环境都支持它,因此我们使用它是非常安全的。

  • 由于 __proto__ 标记在观感上更加明显,所以我们在后面的示例中将使用它。

let user = {setName(name){this.name = name}
}
let admin = {__proto__: user
}
// 即使是调用的继承对象user中的方法, 但是方法中的this依然指向调用者admin
admin.setName("admin");
console.log(admin.name);  // admin
console.log(user.name);  // undefind

我们还记得,可以使用诸如 new F() 这样的构造函数来创建一个新对象。

如果 F.prototype 是一个对象,那么 new 操作符会使用它为新对象设置 [[Prototype]]

"use strict";MyArray.prototype = new Array();   // * 与使用 ** 行, ***行 等效
// Array.prototype = Array.prototype  // **
function MyArray() {// this.__proto__ = new Array();  // ***// this 是一个new出来的具体对象, MyArray 是一个构造函数
}const arr = new MyArray();
// MyArray.prototype上的属性方法可直接使用, 未找到会自动向上寻找, 在`arr.__proto__`上找到constructor方法
console.log(arr.constructor === Array); // true
console.log(arr.__proto__.constructor === Array); // true
// 调用Array.prototype 上的方法
arr.push(...[1, 2, 3]);
console.log(arr);

每个函数都有 "prototype" 属性,即使我们没有提供它。

默认的 "prototype" 是一个只有属性 constructor 的对象,属性 constructor 指向函数自身。

"use strict";function User() {}console.log(Object.getOwnPropertyDescriptors(User.prototype));
/* {constructor: {value: [Function: User],writable: true,enumerable: false,configurable: true}} */
console.log(User.prototype.constructor === User); // true
console.log(User.prototype.__proto__.constructor === Object); // true
console.log(User.prototype.__proto__.__proto__ === null); // true, null没有构造方法const user = new User();
console.log(user.__proto__ === User.prototype); // true
console.log(user.__proto__.__proto__.__proto__ === null); // true, 原型链的尽头是null
// User.prototype 上的属性可直接使用
console.log(user.constructor === User);  // true

在常规对象上,prototype 没什么特别的:

let user = {name: "John",prototype: "Bla-bla" // 这里只是普通的属性
};

默认情况下,所有函数都有 F.prototype = {constructor:F},所以我们可以通过访问它的 "constructor" 属性来获取一个对象的构造器。

"use strict";
function User(name){this.name = name;
}
// 构造方法应加上关键字new调用
let user1 = new User("User1");
console.log(user1);let user2 = new User.prototype.constructor("User2");
console.log(user2);let user3 = new user1.__proto__.constructor("User3");
console.log(user3);let user4 = new user1.constructor("User4");
console.log(user4);  // User { name: 'User4' }User.prototype = {}
let user5 = new user1.constructor("User5");
console.log(user5);  // { name: 'User5' }  是 new Object('User5')的结果, 继续向上找constructoruser1.__proto__ = null  // user1.constructor is not a constructor, 如果给{}, 结果是 [String: 'User6']
let user6 = new user1.constructor("User6");
console.log(user6);  

内建对象的原型挂载着相关属性和方法

可向prototype上添加自定义方法或属性

// 通过原型查看数组, 字符串等相关的函数(可在浏览器环境下直接使用String.prototype)// console.log(Object.getOwnPropertyDescriptors(Array.prototype));
console.log(Object.getOwnPropertyNames(Array.prototype));
/* ['length',      'constructor',    'concat','copyWithin',  'fill',           'find','findIndex',   'lastIndexOf',    'pop','push',        'reverse',        'shift','unshift',     'slice',          'sort','splice',      'includes',       'indexOf','join',        'keys',           'entries','values',      'forEach',        'filter','flat',        'flatMap',        'map','every',       'some',           'reduce','reduceRight', 'toLocaleString', 'toString','at'
] */
// 所有函数或属性名
console.log(Object.getOwnPropertyNames(String.prototype));
/* ['length',            'constructor',   'anchor','big',               'blink',         'bold','charAt',            'charCodeAt',    'codePointAt','concat',            'endsWith',      'fontcolor','fontsize',          'fixed',         'includes','indexOf',           'italics',       'lastIndexOf','link',              'localeCompare', 'match','matchAll',          'normalize',     'padEnd','padStart',          'repeat',        'replace','replaceAll',        'search',        'slice','small',             'split',         'strike','sub',               'substr',        'substring','sup',               'startsWith',    'toString','trim',              'trimStart',     'trimLeft','trimEnd',           'trimRight',     'toLocaleLowerCase','toLocaleUpperCase', 'toLowerCase',   'toUpperCase','valueOf',           'at'
] */
console.log(Object.getOwnPropertyNames(Number.prototype));
/* ['constructor','toExponential','toFixed','toPrecision','toString','valueOf','toLocaleString'
] */
console.log(Object.getOwnPropertyNames(Boolean.prototype));
/* [ 'constructor', 'toString', 'valueOf' ] */console.log(Object.getOwnPropertyNames(Date.prototype));
/* ['constructor',        'toString',           'toDateString','toTimeString',       'toISOString',        'toUTCString','toGMTString',        'getDate',            'setDate','getDay',             'getFullYear',        'setFullYear','getHours',           'setHours',           'getMilliseconds','setMilliseconds',    'getMinutes',         'setMinutes','getMonth',           'setMonth',           'getSeconds','setSeconds',         'getTime',            'setTime','getTimezoneOffset',  'getUTCDate',         'setUTCDate','getUTCDay',          'getUTCFullYear',     'setUTCFullYear','getUTCHours',        'setUTCHours',        'getUTCMilliseconds','setUTCMilliseconds', 'getUTCMinutes',      'setUTCMinutes','getUTCMonth',        'setUTCMonth',        'getUTCSeconds','setUTCSeconds',      'valueOf',            'getYear','setYear',            'toJSON',             'toLocaleString','toLocaleDateString', 'toLocaleTimeString'
] */
console.log(Object.getOwnPropertyNames(Map.prototype));
/* ['constructor', 'get','set',         'has','delete',      'clear','entries',     'forEach','keys',        'size','values'
] */
console.log(Object.getOwnPropertyNames(WeakMap.prototype));
/* [ 'constructor', 'delete', 'get', 'set', 'has' ] */console.log(Object.getOwnPropertyNames(Function.prototype));
/* ['length',      'name','arguments',   'caller','constructor', 'apply','bind',        'call','toString'
] */
console.log(Object.getOwnPropertyNames(Object.prototype));
/* ['constructor','__defineGetter__','__defineSetter__','hasOwnProperty','__lookupGetter__','__lookupSetter__','isPrototypeOf','propertyIsEnumerable','toString','valueOf','__proto__','toLocaleString'
] */
console.log(Object.getOwnPropertyNames(Object));
/* ['length','name','prototype','assign','getOwnPropertyDescriptor','getOwnPropertyDescriptors','getOwnPropertyNames','getOwnPropertySymbols','is','preventExtensions','seal','create','defineProperties','defineProperty','freeze','getPrototypeOf','setPrototypeOf','isExtensible','isFrozen','isSealed','keys','entries','fromEntries','values','hasOwn'
] */

如果速度很重要,就请不要修改已存在的对象的 [[Prototype]]

通常我们只在创建对象的时候设置它一次,自那之后不再修改

现代的获取/设置原型的方法有:

  • Object.getPrototypeOf(obj) —— 返回对象 obj[[Prototype]]
  • Object.setPrototypeOf(obj, proto) —— 将对象 obj[[Prototype]] 设置为 proto

Object.create(null)这样的对象称为 “very plain” 或 “pure dictionary” 对象,因为它们甚至比通常的普通对象(plain object){...} 还要简单。

缺点是这样的对象没有任何内建的对象的方法,例如 toString

'use strict';
// 这个对象没有原型([[Prototype]] 是 null)
// 创建一个以null为原型的对象, 在obj中, __ptoto__、toString等原本的内建属性和方法不复存在, 只是普通的方法和属性
let obj = Object.create(null);console.log(obj.__proto__);  // undefined
// console.log(obj.toString());  // TypeError: obj.toString is not a function// 正常的
let obj1 = {};
console.log(obj1.__proto__);  // [Object: null prototype] {}
console.log(obj1.toString());  // [object Object]
http://www.15wanjia.com/news/47085.html

相关文章:

  • 招聘做牙技工的网站怎么弄一个网站平台
  • 成都市住房和成都市建设委员会网站如何自己开发一个网站
  • 电子商务网站开发视频安全优化大师
  • 最好科技上海网站建设做什么推广最赚钱
  • 整站优化排名百度指数官网移动版
  • 营销型网站需要注意百度有哪些app产品
  • 中企动力主要是做什么的seo短视频网页入口引流免费
  • 网站如何生成app重庆发布的最新消息今天
  • 中国做网站的网站深度优化
  • 惠州网站制作培训沈阳网页建站模板
  • 西安网站制作服务商产品销售方案与营销策略
  • 看到一个电商网站帮做淘宝百度识图在线入口
  • 做企业网站模板可以seo微信指数怎么看
  • joomla 网站建设如何申请域名
  • 用KEGG网站做KEGG富集分析点击器免费版
  • 我的网站域名电商营销
  • 做产品类网站网上销售平台
  • 网站开发语言一般是用什么手机百度搜索引擎入口
  • 香港网站域名申请手机搭建网站
  • 艺商网站代运营靠谱吗
  • 哪个网站能看到学做标书数据分析师就业前景
  • 通州设计网站建设免费发广告的网站
  • 网站备案后会被注销吗百度电脑版登录网站
  • 新手怎么建立网站爆款采集推广引流软件
  • 做校园网站的公司网站营销软文
  • 廉江手机网站建设公司怎么百度推广
  • 国家林草局三北防护林建设局网站win10优化软件
  • seo建站推广深圳新闻今日最新
  • 网站制作怎么做框架关键词代发排名首页
  • 动态网站的常用软件网页设计案例