二、this和对象原型
1、关于this
(1)、this到底是什么?
this是在运行时进行绑定的,并不是在编写是绑定,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数调用方式。
this既不指向函数自身也不指向函数的词法作用域。它指向声明完全取决于函数在哪里被调用。
2、this全面解析
(1)、调用位置
调用位置最重要的是要分析调用栈,调用位置就在当前正在只想函数的前一个调用中。
通过代码看看到底声明是调用栈和调用位置:
function baz(){
//当前调用栈是:baz
//因此,当前调用位置是全局作用域
console.log("baz");
bar();
}
function bar(){
//当前调用栈是baz ->bar
//因此,当前调用位置在baz中
console.log("bar");
foo();//<--foo的调用位置
}
function foo(){
//当前调用栈是baz ->bar->foo
//因此,当前调用位置在foo中
console.log("foo");
}
baz();//<--baz的调用位置
(2)、绑定规则
(a)、默认绑定(独立函数调用)
如下代码:
function foo(){
console.log(this.a);//
}
var a=2;
foo();//2 此时foo()是直接使用不带任何修饰的函数引用进行调用的,因此this是默认绑定,this指向全局变量。
(b)、隐式绑定
隐式绑定规则会吧函数调用中的this绑定到这个上下文对象。它的落脚点指向调用的对象。
如:
function foo(){
console.log(this.a);
}
var obj2 = {
a:42,
foo:foo
}
var obj1 = {
a:2,
obj2:obj2
}
obj1.obj2.foo();// 42 此时this 指向最后一层调用他的对象obj2.所以输出42
另外一个常见的this绑定被隐式绑定的函数丢失绑定对象,会应用默认绑定,从而指向了全局对象,如果是严格模式指向undefied
如:
function foo(){
console.log(this.a);
}
var obj ={
a:2,
foo:foo
}
var bar = obj.foo();
var a = "opps,global";
bar();//"opps,global" bar 是obj.foo的一个引用,但实际上,它引用了foo函数本身。此时bar()等价于直接调用foo()函数,所以this应用了默认绑定规则,指向全局变量。
(c)、显示绑定
直接指定this的绑定对象,称之为显示绑定。通过call(..)或者apply(..)实现显示绑定。
如:
function foo(){
console.log(this.a);
}
var obj={
a:2
}
foo.call(obj);//2 通过foo.call(..),强制把它的this绑定到obj上。
(d)、new 绑定
使用new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
1、创建(或者说构造)一个全新的对象。
2、这个新对象会被执行[[原型]]连接。
3、这个新对象会绑定到函数调用的this.
4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
考虑下面的代码:
function foo(a){
this.a=a;
}
var bar = new foo(2);
console.log(bar.a);//2
使用new 来调用foo(..)时,我们会构造一个新对象并把它绑定到foo(..)调用中的this上。
(3)、判断this的优先级,我们可以按照如下顺序来进行判断:
(a)、函数是否在new中调用(new绑定)?如果是的话,this绑定的是新创建的对象。
var bar = new foo(); //this 是bar对象
(b)、函数是否通过call,apply(显示绑定)?如果是的话,this绑定的是指定的对象。
var bar = foo.call(obj2); //this是obj2对象
(c)、函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。
var bar = obj1.foo(); //this是obj1对象
(d)、如果都不是的话,使用默认绑定,如果在严格模式下,就绑定到undefined,否则绑定到全局对象
var bar =foo(); //this 绑定到全局对象
3、对象
3.1 语法
对象可以通过两种形式定义:声明(文字)形式和构造形式。
(1)、对象的文字语法:
var myobj = {
key :value,
//
}
(2)、构造形式:
var myObj = new Object();
myObj.key = value;
两种方式生成的对象是一样的。
3.2 类型和内置对象
javascript 六种主要类型(语言类型):string、number、boolean、null、undefined、object
javascript 内置对象有:String、Number、Boolean、Object、Function、Array、Date、RegExp、Error
对于string、number、boolean 引擎自动会把字面量转成相应的对象,可以访问其属性和方法。
如:42.359.toFixed(2);引擎把数字自动转成new Number(42.359).
null和undefined没有对应的构造形式,他们只有文字形式。
3.3 对象内容
对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的,我们称之为属性。
对象内容的访问可以通过“属性访问”或“键访问”方式。
如:
var myObject = {
a:2
}
myObject.a;//2 属性访问
myObject["a"];//2 键访问
两种语法的区别在于:.操作符要求属性名满足标识符的命名规范,而[".."]键访问语法可以接受任意UTF-8/Unicode字符串作为属性名。
3.4 可计算属性名
可计算属性名是只属性名是动态的。可以在文字形式中使用[]包裹表达式来当做属性名:
如下代码:
var prefix = "foo";
var myObject = {
[prefix+"bar"]:"hello",
[prefix+"baz"]:"world"
}
myObject["foobar"];//hello
myObject["foobaz"];//world
3.5 属性描述符
ES5开始所有的属性都具备了属性描述符。如下代码:
var myObject = {a:2}
Object.getOwnPropertyDescriptor(myObject,"a");
//{value: 2, writable: true, enumerable: true, configurable: true}
普通对象属性还包括另外三个特性:writalbe(可写)、enumerable(可枚举)和configurable(可配置)
我们也可以使用Object.defineProperty(..)来添加或修改一个已有属性。
如:
var myObject={};
Object.defineProperty(myObject,"a",{
value:2,
writable:false,//不可写!
configurable:true,
enumerable:true
});
myObject.a=3;//写属性false,这里不能重新赋值
myObject.a;//2
(1)、禁止扩展
禁止一个对象添加新属性并且保留已有属性,可以使用Object.preventExtensions(..)
(2)、密封
Object.seal(..)会创建一个“密封”的对象,不能添加也不能配置或删除任何现有属性。
(3)、冻结
Object.freeze(..)会创建一个冻结对象,这样无法修改他们的值。
属性可以是可枚举或者不可枚举的,这决定了它们是否会出现在for .. in循环中。Object.keys返回一个对象属性值的数组。
4、原型
4.1 [[Prototype]]
javascript 中的对象有一个特殊的[[Prototype]]内置属性,其实就是对于其他对象的应用。
如果要访问对象中并不存在的一个属性,[[Get]]操作就会查找对象内部[[Prototype]]关联的对象,这个关联关系实际上定义了一条“原型链”,在查找属性时会对它进行遍历。
所有普通对象都有内置的Object.prototype,指向原型链的顶端,如果在原型链中找不到指定的属性就会停止。toString()、valueOf()和其他一些通用的功能都存在于Object.property对象上,因此语言中所有的对象都可以使用它们。
关联两个对象最常用的方法是使用new 关键词进行函数调用,在调用中会创建一个关联其他对象的新对象。
使用new 调用函数时会把新对象的.prototype属性关联到“其他对象”。带new的函数调用通常称为“构造函数调用”,尽管他们实际上和传统面向累语言中的类构造函数不一样。
对象之间关系不是复制而是通过内部的[[Prototype]]链关联,是一种委托。
5、行为委托
5.1 面向委托的设计
行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。
相关推荐
最后,面向对象的基础知识也是不可或缺的,由于JavaScript的面向对象实现方式比较特殊,所以学习者需要了解正统的面向对象编程基础。 创建对象是面向对象编程的基础。在JavaScript中创建对象有多种方式,最简单的一...
【标题】: "你不懂JS:this与对象原型.pdf" 【描述】: 该文档主要探讨了JavaScript中的核心概念,特别是`this`关键字和对象原型。它旨在帮助读者理解这两个概念在JavaScript中的工作原理,以及它们如何影响代码的...
以下是对JavaScript面向对象和原型机制的详细解释: 1. 面向对象的基本概念: - 类:在许多面向对象语言中,类是创建对象的模板,但在JavaScript中没有类的概念。 - 对象:JavaScript中的对象是一组键值对,可以...
JavaScript中的原型对象、this的五种用法、原型继承以及Caller和Callee的使用是JavaScript编程中的核心概念。首先,让我们深入理解每个概念。 **原型对象(Prototype)** 在JavaScript中,每当定义一个函数,都会...
《JavaScript内核系列》和《JavaScript面向对象基础》这两本书是深入理解JavaScript编程的重要资源。JavaScript,作为一种广泛应用于Web开发的脚本语言,其内核和面向对象特性是开发者必须掌握的基础知识。以下是对...
深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP 深入理解JavaScript系列(7):S.O.L.I.D五大原则之开闭原则OCP 深入理解JavaScript系列(8):...
JavaScript原型链是JavaScript语言中的一个核心特性,它关乎对象之间的继承关系。在JavaScript中,一切皆为对象,而原型链则是...因此,深入学习和掌握JavaScript原型链对于任何JavaScript开发者来说都是必不可少的。
### JavaScript学习深入—面向对象编程 #### 一、JavaScript中的类型概述 JavaScript作为一种动态的、弱类型的语言,其核心特点之一在于它灵活的对象模型。尽管JavaScript的基础架构支持面向对象编程(OOP),但在...
JavaScript是一种广泛应用于Web开发的脚本语言,尤其在前端领域占据着核心地位。面向对象编程(Object-Oriented Programming,OOP)是...学习这些材料将有助于深入理解JavaScript的面向对象编程,提升你的编程技能。
JavaScript引擎在查找属性时会沿着原型链查找,如果在实例对象本身找不到,就会去原型对象中寻找,直到找到`null`(这是原型链的终点),表示没有找到。 总结一下,JavaScript中的实例对象与原型对象的关系是: 1. ...
总的来说,这个练习旨在让学习者掌握JavaScript中原型对象和原型链的核心概念,以及如何在实际项目中运用这些知识。通过动手实践,学生们将能更深刻地理解JavaScript的对象继承机制,并提高他们的编程能力。
JavaScript中的原型模式是一种实现面向对象编程(OOP)的关键机制,它基于原型继承,使得对象可以从其他对象那里获得属性和方法。在这个模式下,每个函数都有一个`prototype`属性,这个属性是一个对象,用于共享属性...
深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6):S O L I D五大原则之单一职责SRP 深入理解JavaScript系列(7):S O L I D五大原则之开闭原则OCP 深入理解JavaScript系列(8):...
一个例子让你彻底明白原型对象和原型链 开篇 之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂...
当访问某个对象中的一个不存在的属性或方法时,会自动调用原型中的属性和方法。也就是说,基于原型创建的对象会自动拥有原型的属性和方法。 之前我们学过构造函数,通过构造函数也可以使两个对象具有相同的属性和...
4. 继承:在JavaScript中,对象可以通过原型链继承其他对象的属性和方法。原型链是一个对象的原型可以指向另一个对象的原型,这样就在不同对象间形成了一条链,从而实现继承。 5. 封装:封装是面向对象编程的一个...
在JavaScript中,面向对象主要通过构造函数、原型链、原型对象和闭包等机制来实现。 1. **构造函数**:构造函数在JavaScript中扮演着类的角色,它们通常用来初始化新创建的对象。我们可以通过`new`关键字调用构造...
JavaScript对象是编程语言的核心组成部分,尤其在Web开发中扮演着至关重要的角色。"JavaScript对象参考手册"涵盖了这一...通过深入学习,你将能够更好地理解和应用JavaScript对象,从而提升你的编程技能和项目质量。