第4页 this和对象
- 章节名:this和对象
- 页码:第4页
this既不指向函数自身也不指向函数的词法作用域 this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。 当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this就是记录的其中一个属性,会在函数执行的过程中用到。 引自 this和对象 JavaScript语言和宿主环境中许多新的内置函数,都提供了一个可选的参数,通常被称为“上下文”(context),其作用和bind(..)一样,确保你的回调函数使用指定的this。
Array.prototype.forEach() //arr.forEach(callback[, thisArg]) Array.prototype.map() //array.map(callback[, thisArg])
function bind(fn, obj) { return function() { fn.apply( obj, arguments ); }; } function foo(something) { this.a = something; } var obj1 = {}; var bar = foo.bind(obj1); var bar2 = bind(foo,obj1) bar(2); bar2(2); console.log('obj1.a is' + obj1.a); // 2 var baz = new bar(3); console.log('obj1.a is' + obj1.a); // 2 console.log(baz.a); // 3 var baz2 = new bar2(3); console.log('obj1.a is' + obj1.a);//3 console.log(baz2.a); // undefined辅助函数bind中new操作符的调用无法修改this绑定,ES5内置函数可以,更复杂的MDN Polyfill 箭头函数的this绑定无法被修改。(new也不行!)
function foo2() { return function(a) { console.log(this.a); }; } function foo() { // 返回一个箭头函数 return (a) => { //this继承自foo() console.log(this.a); }; } var obj1 = { a: 2 }; var obj2 = { a: 3 }; var bar = foo.call(obj1); bar.call(obj2); // 2, 不是3! var bar2 = foo2.call(obj1); bar2.call(obj2); // 3箭头函数根据当前的词法作用域来决定this,会继承外层函数调用的this绑定(无论this绑定到什么)。和ES6之前代码中的self = this机制一样。 基本类型(string、boolean、number、null和undefined)本身并不是对象。null有时会被当作一种对象类型,但是这其实只是语言本身的一个bug,即对null执行typeof null时会返回字符串"object"。1实际上,null本身是基本类型。 不同的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型,null的二进制表示是全0,自然前三位也是0,所以执行typeof时会返回“object”。
Object.getPrototypeOf(null) //TypeError从技术角度来说,函数永远不会“属于”一个对象,所以把对象内部引用的函数称为“方法”似乎有点不妥。 最保险的说法可能是,“函数”和“方法”在JavaScript中是可以互换的。 对于JSON安全(也就是说可以被序列化为一个JSON字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)的对象来说,有一种巧妙的复制方法:
var newObj = JSON.parse( JSON.stringify( someObj ) );
var myObject = { a: 2 }; Object.defineProperty(myObject, "a", { value: 4, writable: true, configurable: false, // 不可配置! enumerable: true }); myObject.a; // 4 myObject.a = 5; myObject.a; // 5 Object.defineProperty(myObject, "a", { value: 6, writable: true, configurable: true, enumerable: true }); // TypeErrorconfigurable修改成false是单向操作,无法撤销! 一个例外:即便属性是configurable:false, 我们还是可以把writable的状态由true改为false,但是无法由false改为true。 所有的普通对象都可以通过对于Object.prototype的委托来访问hasOwnProperty(..) 没有连接到Object.prototype的对象(如通过Object.create(null)来创建的用
Object.prototype.hasOwnProperty.call(myObject,"a")
var myObject = {}; Object.defineProperty(myObject, "a", // 让a像普通属性一样可以枚举 { enumerable: true, value: 2 }); Object.defineProperty(myObject, "b", // 让b不可枚举 { enumerable: false, value: 3 }); myObject.propertyIsEnumerable("a"); // true myObject.propertyIsEnumerable("b"); // false Object.keys(myObject); // ["a"] 可枚举 Object.getOwnPropertyNames(myObject); // ["a", "b"] 所有属性Object.keys(..)和Object.getOwnPropertyNames(..)都只会查找对象直接包含的属性。 (目前)并没有内置的方法可以获取in操作符使用的属性列表(对象本身的属性以及[[Prototype]]链中的所有属性 内置的@@iterator来手动遍历数组
var myArray = [1, 2, 3]; var it = myArray[Symbol.iterator](); it.next(); // { value:1, done:false } it.next(); // { value:2, done:false } it.next(); // { value:3, done:false } it.next(); // { done:true }给任何想遍历的对象定义@@iterator
var myObject = { a: 2, b: 3 }; Object.defineProperty(myObject, Symbol.iterator, { enumerable: false, writable: false, configurable: true, value: function() { var o = this; var idx = 0; var ks = Object.keys(o); return { next: function() { return { value: o[ks[idx++]], done: (idx > ks.length) }; } }; } }); // 手动遍历myObject var it = myObject[Symbol.iterator](); it.next(); // { value:2, done:false } it.next(); // { value:3, done:false } it.next(); // { value:undefined, done:true } // 用for..of遍历myObject for (var v of myObject) { console.log(v); } // 2 // 3也可以直接在定义对象时进行声明,比如var myObject = { a:2, b:3, [Symbol.iterator]: function() { /* .. */ } }。 定义一个“无限”迭代器,它永远不会“结束”并且总会返回一个新值(比如随机数、递增值、唯一标识符,等等)
var randoms = { [Symbol.iterator]: function() { return { next: function() { return { value: Math.random() }; } }; } }; var randoms_pool = []; for (var n of randoms) { randoms_pool.push(n); // 防止无限运行! if (randoms_pool.length === 100) break; }
○对本书的所有笔记 · · · · · ·
-
第2页 模块机制
5.5.1 var MyModules = (function Manager() { var modules = {}; function define(name, dep...
-
第3页 第一部分 附录
动态作用域 function foo() { console.log(a); // 2 } function bar() { var a = 3; foo(); }...
-
第4页 this和对象
-
第5页 原型和委托
对于默认的[[Get]]操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象的[[Protot...
说明 · · · · · ·
表示其中内容是对原文的摘抄