好想要对象···

  函数的调用位置不同会造成this绑定对象不同。但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂)

  

语法

  对象声明有两个形式:

  1、字面量 => var obj = { ... };

  2、构造形式 => var obj = new Object();

  两种形式生成的对象是一样的,唯一的区别是,在文字声明中可以添加多个键值对,构造形式只能逐个添加。

类型

  JS中有六种主要类型:string、number、booleam、null、undefined、object。

  注意,简单数据类型本身并不是对象,null有时会被当成一种对象类型,但是这其实只是语言本身的一个bug,即对null执行typeof null时会返回字符串object。实际上,null本身是基本类型。(原理是这样的,不同的对象在底层都表现为二进制,在JS中二进制的前三位都为0的话会被判断为object类型,null的二进制表示是全0,所以执行时会返回object。)

  有一种常见的错误是‘万物皆对象’,这显示是错误的(我去,被老师骗了)。

  实际上,JS中有许多特殊的对象子类型,称之为复杂基本类型。

  函数就是对象的一个子类型(技术角度来讲叫可调用对象)。JS中的函数是‘一等公民’,因为它们本质上和普通对象一样,所以可以像操作其他对象一样操作函数。

  数组也是对象的一种类型。

内置对象

  JS有一些对象子类型,通常被称为内置对象。

  包括String、Number、Boolean、Object、Function、Array、Date、RegExp、Error。

  内置对象可以当作构造函数来使用,从而可以构造一个对应子类型的新对象。

  如果用字面量形式创建number、string(var str = 'jimmy',num = 1),调用对象方法(length)时会自动转换成对象并调用方法,然后还原为基本数据类型返回,这个过程是不可见的。但是也没有必要为了性能特地通过构造形式声明基本数据,这种转换十分频繁,所以底层已经做了优化,用字面量更好更快。

  null和undefined没有对应的构造形式,只有文字形式。

  Date只有构造,没有文字形式。

  对于Object、Array、Function、RegExp来说,无论使用哪种形式出来的都是对象。

  Error对象很少在代码中显示创建,一般在抛出异常的时候被自动创建。也可以用new Error()这种构造形式创建,一般来说,用不着。

  报错误信息,vue源码中用了console.error(),如下代码:

    warn = function(msg, vm) {
if (hasConsole && (!config.silent)) {
console.error("[Vue warn]: " + msg + " " + (
vm ? formatLocation(formatComponentName(vm)) : ''
));
}
};

  专门用来生成错误信息的函数,jQuery源码中反正是没见着,尤大还是很贴心的。

内容

  对象内容由键值对组成,键更像是一个指针,保存内容所在存储位置的地址。(ES6之前,不支持奇怪的键,所以只能用普通字符串定义键)

  可以用点访问和[]访问键,主要区别是点访问属性名必须满足标识符的命名规范,而[]可以接受任意形式的字符串。

  还有一个细微差别:

    function fn(a) {
console.log(obj.a); //undefined
console.log(obj[a]); //
}
var obj = {
ab: 1,
}
fn('ab');

  当访问的属性名作为参数传入函数时,使用[]访问才能正常得到结果。

  在对象中,属性名永远是字符串,如果使用其余类型的值作为属性名,会被强制调用toString方法。

    var obj = {}
obj[true] = 1;
obj[1] = 2;
obj[obj] = 3;
console.log(obj['true']); //
console.log(obj['1']); //
console.log(obj['[object Object]']); //

  好玩!

可计算属性名

  ES6中可以使用表达式计算属性名。

    var str = 'jimmy';
var obj = {
[str + 'a']: 1,
[str + 'b']: 2
}
console.log(obj.jimmya); //
console.log(obj.jimmyb); //

  

属性和方法

  如果属性访问的是函数,一般称为方法访问。技术上来讲,函数不属于任何对象,所有对函数的访问只是引用而已。

  数组也可以随便添加属性,但是不要这样做,数组对特殊行为和用途进行了优化。

复制对象

  对于JSON安全的对象来说,可以用下面方法来实现深复制:

    var newobj = JSON.parse(JSON.stringify(oldobj));

  浅复制比较简单,ES6中定义了Object.assign()方法。第一个参数是目标对象,之后还可以跟多个源对象。

  jQuery中实现深复制的代码如下:

    jQuery.extend = jQuery.fn.extend = function() {
var options, name, src, copy, copyIsArray, clone,
target = arguments[0] || {},
i = 1,
length = arguments.length,
deep = false;
//参数修正
if (typeof target === "boolean") {
deep = target;
target = arguments[i] || {};
i++;
}
if (typeof target !== "object" && !jQuery.isFunction(target)) {
target = {};
}
if (i === length) {
target = this;
i--;
}
for (; i < length; i++) {
if ((options = arguments[i]) != null) {
for (name in options) {
src = target[name];
copy = options[name];
if (target === copy) {
continue;
}
if (deep && copy && (jQuery.isPlainObject(copy) ||
(copyIsArray = jQuery.isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && jQuery.isArray(src) ? src : [];
} else {
clone = src && jQuery.isPlainObject(src) ? src : {};
}
target[name] = jQuery.extend(deep, clone, copy);
} else if (copy !== undefined) {
target[name] = copy;
}
}
}
}
return target;
};

[[Get]]/取值操作

  属性访问有一个细节。

    var obj = {
a: 1,
}
console.log(obj.a); //

  在语言规范中,obj.a在obj上实际上是实现了[[Get]]操作。对象默认的内置[[Get]]操作首先在对象中查找是否有名称相同的属性,如果找到就返回这个属性的值。

  如果没有找到名称相同的属性,按照[[Get]]算法的定义会执行另外一种非常重要的行为,遍历原型链。

  如果在原型链的顶端也没有找到,会返回undefined。

[[Put]]/赋值操作

  有[[Get]],就会有[[Put]]([[put]]没太懂为什么用这个词)。

  [[Put]]被触发时,实际行为取决于许多因素,包括对象是否已经存在这个属性。

  如果已经存在这个属性,[[Put]]算法大概如下:

  1、属性是否是访问描述符?如果是并且存在setter就调用setter。

  2、属性的描述符中writable是否是false?如果是,非严格模式忽略,严格模式报错。

  3、如果都不是,将该值设置为属性的值。

  如果不存在,[[Put]]操作会更复杂。

Getter/Setter

  对象默认的[[Put]]和[[Get]]操作分别可以控制属性值的设置和获取。

  在ES5中可以使用getter和setter部分改写默认操作,但是只能应用在单个属性上,无法应用在整个对象上。getter是一个隐藏函数,会在获取属性值时默认调用。setter也是一个隐藏函数,会在设置属性值时调用。

  当你给一个属性定义getter、setter或者两者都有时,这个属性会被定义为‘访问描述符’。对于访问描述符来说,JS会忽略它们的value和writable特性,取而代之的是关心set和get特性。

    var obj = {
get a() {
return 2;
}
}
console.log(obj.a); //
//未定义set方法 无效
//即便有set 由于定义的get只会返回2 所以没有意义
obj.a = 3;
console.log(obj.a); //
Object.defineProperty(obj, 'b', {
get() {
return this.a * 2;
},
enumerable: true
});
console.log(obj.b); //

  两种定义都会在对象中创建一个不包含值的属性,对于这个属性的访问会自动调用一个隐藏函数,它的返回值会被当作属性访问的返回值。

  

    var obj = {
// 获取值
get a() {
return this.b;
},
// 赋值返回2倍的值
set a(val) {
return this.b = val * 2;
}
}
obj.a = 2;
console.log(obj.a); //

  设置对应的set和get。

读书笔记-你不知道的JS上-对象的更多相关文章

  1. 读书笔记-你不知道的JS上-this

    关于this 与静态词法作用域不用,this的指向动态绑定,在函数执行期间才能确定.感觉有点像C++的多态? var a = 1; var obj = { a: 2, fn: function() { ...

  2. 读书笔记-你不知道的JS上-混入与原型

    继承 mixin混合继承 function mixin(obj1, obj2) { for (var key in obj2) { //重复不复制 if (!(key in obj1)) { obj1 ...

  3. 读书笔记-你不知道的JS上-闭包与模块

    闭包定义 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行. 看一段最简单的闭包代码: function foo() { var a = 2; //闭包 fun ...

  4. 读书笔记-你不知道的JS上-函数作用域与块作用域

    函数作用域 Javascript具有基于函数的作用域,每声明一个函数,都会产生一个对应的作用域. //全局作用域包含f1 function f1(a) { var b = 1; //f1作用域包含a, ...

  5. 读书笔记-你不知道的JS上-词法作用域

    JS引擎 编译与执行 Javascript引擎会在词法分析和代码生成阶段对运行性能进行优化,包含对冗余元素进行优化(例如对语句在不影响结果的情况下进行重新组合). 对于Javascript来说,大部分 ...

  6. 读书笔记-你不知道的JS上-声明提升

    变量声明提升 Javascript代码一般情况下是由上往下执行的,但是有些情况下不成立. a = 2; //变量声明被提升在当前作用域顶部 var a; console.log(a); console ...

  7. 读书笔记-你不知道的JS中-promise

    之前的笔记没保存没掉了,好气,重新写! 填坑-- 现在与将来 在单个JS文件中,程序由许多块组成,这些块有的现在执行,有的将来执行,最常见的块单位是函数. 程序中'将来'执行的部分并不一定在'现在'运 ...

  8. 读书笔记-你不知道的JavaScript(上)

    本文首发在我的个人博客:http://muyunyun.cn/ <你不知道的JavaScript>系列丛书给出了很多颠覆以往对JavaScript认知的点, 读完上卷,受益匪浅,于是对其精 ...

  9. 读书笔记-你不知道的JS中-promise(2)

    继续填坑 模式 考虑下面的代码: function fn(x) { //do something return new Promise(function(resolve, reject) { //调用 ...

随机推荐

  1. Redis的安装以及在项目中使用Redis的一些总结和体会

    第一部分:为什么我的项目中要使用Redis 我知道有些地方没说到位,希望大神们提出来,我会吸取教训,大家共同进步! 注册时邮件激活的部分使用Redis 发送邮件时使用Redis的消息队列,减轻网站压力 ...

  2. MUI开发记录

    最近很久没有更新博客了,因为一直在学习前端h5 手机app的开发.曾经一度觉得自己css和js学得不错,进入到前端领域后才发现水很深~ HUuilder使用安卓模拟器 安卓模拟器有很多,我这里以夜神模 ...

  3. AngularJS--控制器(Controller)

    点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 理解控制器 在AngularJS的控制器中,构造函数会有Scope参数. 当一个控制器通 ...

  4. Java IO学习笔记(一)

    一.概念 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.在两设备间的传输的数据称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,以进行数据操作. 二.流分类 数据类型 ...

  5. ObjectSNMP

    下面的例子,就是使用ObjectSNMP获取RFC1213-MIB的例子:其中的system和ifTable对象就是对应的SNMPMIB中的system组合interface中的ifTable表. p ...

  6. Json操作问题总结

    大家都知道,Json是一种轻量级的数据交换格式,对JS处理数据来说是很理想滴! 熟练写过xxx.json文件和操作的小伙伴来说,我说的问题都不是什么大问题啦,可以忽略本宝宝的文章,更希望各位大佬指点一 ...

  7. bzoj4198 荷马史诗 哈夫曼编码

    逐影子的人,自己就是影子. --荷马 Allison 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但是由<奥德赛>和&l ...

  8. Fix “Could not flush the DNS Resolver Cache: Function failed during execution” When Flushing DNS

    ipconfig /flushdns It is possible that you’re getting an error message “Could not flush the DNS Reso ...

  9. ASP.Net MVC 布局页 模板页 使用方法详细说明

    一.Views文件夹 -> Shared文件夹下的 _Layout.cshtml 母版页 @RenderBody 当创建基于_Layout.cshtml布局页面的视图时,视图的内容会和布局页面合 ...

  10. wxPython中菜单、按钮学习

    ---恢复内容开始--- wx.Window 是一个基类,许多构件从它继承.包括 wx.Frame 构件.技术上这意味着,我们可以在所有的 子类中使用 wx.Window 的方法.我们这里介绍它的几种 ...