js_面向对象_new关键字_对象与this_ES6种对象相关的特性实例

字面量对象

重新介绍 JavaScript(JS 教程) - JavaScript | MDN (mozilla.org)

  • 对象作为函数参数:

在经典的面向对象语言中,对象是指数据和在这些数据上进行的操作的集合。与 C++ 和 Java 不同,JavaScript 是一种基于原型的编程语言,并没有 class 语句,而是把函数用作类。那么让我们来定义一个人名对象,这个对象包括人的姓和名两个域(field)。名字的表示有两种方法:“名 姓(First Last)”或“姓, 名(Last, First)”。使用我们前面讨论过的函数和对象概念,可以像这样完成定义:

function makePerson(first, last) {
    return {
        first: first,
        last: last
    };
}
function personFullName(person) {
    return person.first + ' ' + person.last;
}
function personFullNameReversed(person) {
    return person.last + ', ' + person.first;
}

var s = makePerson('Simon', 'Willison');
personFullName(s); // "Simon Willison"
personFullNameReversed(s); // "Willison, Simon"

利用返回对象的函数创建对象

function makePerson(first, last) {
    return {
        first: first,
        last: last
    };
}

利用关键字new调用构造函数(constructor)来得到(或者说constructor修改一个空对象)得到想要的对象

利用原型链修改对象模板中的属性/方法

function Person(first, last) {
    this.first = first;
    this.last = last;
}
Person.prototype.fullName = function() {
    return this.first + ' ' + this.last;
}
Person.prototype.fullNameReversed = function() {
    return this.last + ', ' + this.first;
}

原型对象

Person.prototype 是一个可以被 Person的所有实例共享的对象。

它是一个名叫 原型链(prototype chain)的 查询链的一部分:当你试图访问 Person<span>某个实例(例如上个例子中的s)一个没有定义的属性时,解释器会首先检查这个 Person.prototype来判断是否存在这样一个属性。

所以,任何分配给 Person.prototype的东西对通过 this 对象构造的实例都是可用的。

这个特性功能十分强大,JavaScript 允许你在程序中的任何时候修改原型(prototype)中的一些东西,也就是说你可以在运行时(runtime)给已存在的对象添加额外的方法:

s = new Person("Simon", "Willison");
s.firstNameCaps();  // TypeError on line 1: s.firstNameCaps is not a function

Person.prototype.firstNameCaps = function() {
    return this.first.toUpperCase()
}
s.firstNameCaps(); // SIMON

new与构造函数(结合this)

实现一个和 new关键字有类似效果的 trivial方法:

  • 下面是一个new 方法的简单实现:
function trivialNew(constructor, ...args) {
    var o = {}; // 创建一个对象
    constructor.apply(o, args);
    return o;
}

note:

这并不是 new 的完整实现,因为它没有创建原型(prototype)链。

(想举例说明 new 的实现有些困难)l因为你不会经常用到这个,但是适当了解一下还是很有用的。

在这一小段代码里,...args(包括省略号)叫作剩余参数(rest arguments)。如名所示,这个东西包含了剩下的参数。

因此,调用

var bill = trivialNew(Person, "William", "Orange");

可认为和调用如下语句是等效的

var bill = new Person("William", "Orange");

this

关键字 this。当使用在函数中时,this 指代当前的对象,也就是 调用了函数的对象

如果在一个对象上使用 点或者方括号来访问属性或方法,这个对象就成了 this。

否则, this 将指向全局对象(global object)。这是一个经常出错的地方。

使用关键字 this 改进已有的 makePerson函数:

function Person(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = function() {
        return this.first + ' ' + this.last;
    }
    this.fullNameReversed = function() {
        return this.last + ', ' + this.first;
    }
}
var s = new Person("Simon", "Willison");

我们引入了另外一个关键字:new,它和 this 密切相关。

它(new)的作用是创建一个崭新的 空对象{},然后使用指向那个对象的 this调用特定的函数。

注意,含有 this的特定函数不会返回任何值,只会修改 this 对象本身。


new关键字将生成的 this对象返回给调用方,而被 new调用的函数称为构造函数。(是的,只是某个函数被new调用了,那么被调用的函数就叫构造函数;但是一般的,我们会让new调用一个适合用来创建的对象的函数,习惯上,这样的被设计为初始化对象的函数首字母大写,这样用new 调用他们的时候就容易识别了)

指定this(对象)来调用基于该this对象的面向对象的方法

  • 用对象obj.FunctionName()obj[FunctionName]()的行形式调用,方法中的this指的就是obj
  • 用函数对象的apply():
    • FunctionName.apply(thisArg,argArray)
  • 用函数对象的call():
    • FunctionName.call(thisArg,argList)

call()

知道了 newthis的基本特点和工作原理后,我们看一下 call()

function Product(name, price) {
    this.name = name;
    this.price = price;
}

function Food(name, price) {
    Product.call(this, name, price);
    this.category = 'food';
}

console.log(new Food('cheese', 5));//Food { name: 'cheese', price: 5, category: 'food' }
console.log(new Food('cheese', 5).name);// expected output: "cheese"
console.log((new Food('cheese', 5)).name);//the same as `new Food('cheese',5).name`
console.log(Food('cheese', 5));//expected undefined
// console.log(new (Food('cheese',5).name));// Wrong! TypeError
// console.log(Food('Cheese',5).name);//Wrong! TypeError
console.log();

这里,

<strong>call()</strong>方法使用 一个指定的 this 值和 单独给出的一个或多个参数调用一个函数

注意: 该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表 ,而 apply() 方法接受的是一个包含多个参数的数组

对于本例代码,的new调用处,创建了一个空对象,然后用该空对象的this去调用函数Food(),Food()将会对这个空对象进行处理,Food()内部调用了Product函数对象的call()方法,该方法将空对象作为this实参,后面的name,price参数列表将传递给Product()函数,这样函数Product所作用于的对象this就是new出来的空对象的this.

new还将生成的this对象返回给调用方(本例的测试中对这个new 所调用的构造函数修饰后的this对象调用(访问)了其name属性.

new 小结

总之,new 是基于新建一个空对象 {}的基础上执行一些操作

apply()

call()中的例子用apply()来改写:

function Food(name, price) {
    Product.apply(this, [name, price]);
    this.category = 'food';
}

apply()示例 (mozilla.org)

ES6种对象相关的特性

obj = {
    d: console.log,
    name: "NameInObj",
    data: {
        name: "nameIndataOfobj",
        age: 18
    },

    methodInObj: function () {
        console.log(this.data.name);
        console.log(this.data.age);
        this.d(this.data);
        // console.log(name);

    },
    /* 定义函数的若干种方式: */
    m1: function () {
        console.log("I am the method1😎");

    },
    /* 简化写法m1:将`:function`省略掉 */
    m2() {
        console.log("I am the method2❤️");
    }
    ,
    /* 测试箭头函数的对象绑定特性 */
    testThis() {
        const that = this;
        setTimeout(
            function () {
                console.log(this.name + " 😎test this within setTimeOut(expected undefined)");
            }
        );
        setTimeout(
            function () {
                console.log(that.name + " 😎test this within setTimeOut(expected name in obj)");
            }
        );
        setTimeout(() => {
            console.log(this.name + ` 👌test that within settimeOut(expected name in obj) `);
        }, 0);
    }
};


function testmethod() {

    obj.methodInObj;
    obj.methodInObj();
    console.log(obj.methods);
}
// console.log(obj.methods());
// console.log(obj);

function testMn() {
    obj.m1();
    obj.m2();
}
// testMn()

obj.testThis();

posted @ 2023-07-11 10:36  xuchaoxin1375  阅读(8)  评论(0)    收藏  举报  来源