`

你不知道的javascript系列学习(this和对象原型)

 
阅读更多

 

二、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 面向委托的设计

行为委托认为对象之间是兄弟关系,互相委托,而不是父类和子类的关系。

 

分享到:
评论

相关推荐

    第15章 javascript面向对象与原型

    最后,面向对象的基础知识也是不可或缺的,由于JavaScript的面向对象实现方式比较特殊,所以学习者需要了解正统的面向对象编程基础。 创建对象是面向对象编程的基础。在JavaScript中创建对象有多种方式,最简单的一...

    你不懂JS:this与对象原型.pdf

    【标题】: "你不懂JS:this与对象原型.pdf" 【描述】: 该文档主要探讨了JavaScript中的核心概念,特别是`this`关键字和对象原型。它旨在帮助读者理解这两个概念在JavaScript中的工作原理,以及它们如何影响代码的...

    JavaScript 面向对象与原型

    以下是对JavaScript面向对象和原型机制的详细解释: 1. 面向对象的基本概念: - 类:在许多面向对象语言中,类是创建对象的模板,但在JavaScript中没有类的概念。 - 对象:JavaScript中的对象是一组键值对,可以...

    Javascript原型对象、this的5钟用法、原型继承、Caller和Callee的使用.docx

    JavaScript中的原型对象、this的五种用法、原型继承以及Caller和Callee的使用是JavaScript编程中的核心概念。首先,让我们深入理解每个概念。 **原型对象(Prototype)** 在JavaScript中,每当定义一个函数,都会...

    《JavaScript内核系列》和《JavaScript面向对象基础》

    《JavaScript内核系列》和《JavaScript面向对象基础》这两本书是深入理解JavaScript编程的重要资源。JavaScript,作为一种广泛应用于Web开发的脚本语言,其内核和面向对象特性是开发者必须掌握的基础知识。以下是对...

    深入理解JavaScript系列

    深入理解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是一种广泛应用于Web开发的脚本语言,尤其在前端领域占据着核心地位。面向对象编程(Object-Oriented Programming,OOP)是...学习这些材料将有助于深入理解JavaScript的面向对象编程,提升你的编程技能。

    举例说明JavaScript中的实例对象与原型对象_.docx

    JavaScript引擎在查找属性时会沿着原型链查找,如果在实例对象本身找不到,就会去原型对象中寻找,直到找到`null`(这是原型链的终点),表示没有找到。 总结一下,JavaScript中的实例对象与原型对象的关系是: 1. ...

    原生JS原型对象练习

    总的来说,这个练习旨在让学习者掌握JavaScript中原型对象和原型链的核心概念,以及如何在实际项目中运用这些知识。通过动手实践,学生们将能更深刻地理解JavaScript的对象继承机制,并提高他们的编程能力。

    javascript 原型模式实现OOP的再研究

    JavaScript中的原型模式是一种实现面向对象编程(OOP)的关键机制,它基于原型继承,使得对象可以从其他对象那里获得属性和方法。在这个模式下,每个函数都有一个`prototype`属性,这个属性是一个对象,用于共享属性...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6):S O L I D五大原则之单一职责SRP 深入理解JavaScript系列(7):S O L I D五大原则之开闭原则OCP 深入理解JavaScript系列(8):...

    js 原型对象和原型链理解

    一个例子让你彻底明白原型对象和原型链 开篇 之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂...

    JavaScript程序设计课件:原型与继承.pptx

    当访问某个对象中的一个不存在的属性或方法时,会自动调用原型中的属性和方法。也就是说,基于原型创建的对象会自动拥有原型的属性和方法。 之前我们学过构造函数,通过构造函数也可以使两个对象具有相同的属性和...

    JavaScript面向对象编程指南.pdf

    4. 继承:在JavaScript中,对象可以通过原型链继承其他对象的属性和方法。原型链是一个对象的原型可以指向另一个对象的原型,这样就在不同对象间形成了一条链,从而实现继承。 5. 封装:封装是面向对象编程的一个...

    面向对象JavaScript开发

    在JavaScript中,面向对象主要通过构造函数、原型链、原型对象和闭包等机制来实现。 1. **构造函数**:构造函数在JavaScript中扮演着类的角色,它们通常用来初始化新创建的对象。我们可以通过`new`关键字调用构造...

    javascript对象参考手册

    JavaScript对象是编程语言的核心组成部分,尤其在Web开发中扮演着至关重要的角色。"JavaScript对象参考手册"涵盖了这一...通过深入学习,你将能够更好地理解和应用JavaScript对象,从而提升你的编程技能和项目质量。

Global site tag (gtag.js) - Google Analytics