蔚来ES6作为一个纯电动汽车,为何价格这么高?

发布网友

我来回答

14个回答

懂视网

顺便注意这是一个 ES5 的方法。

举个例子:

const foo = { value: 1 };
const bar = Object.getOwnPropertyDescriptor(foo, "value");
// bar {
// value: 1,
// writable: true
// enumerable: true,
// configurable: true,
// }

const foo = { get value() { return 1; } };
const bar = Object.getOwnPropertyDescriptor(foo, "value");
// bar {
// get: /*the getter function*/,
// set: undefined
// enumerable: true,
// configurable: true,
// }

第一部分源码解析

在 _applyDecoratedDescriptor 函数内部,我们首先将 Object.getOwnPropertyDescriptor() 返回的属性描述符对象做了一份拷贝:

// 拷贝一份 descriptor
var desc = {};
Object["ke" + "ys"](descriptor).forEach(function(key) {
 desc[key] = descriptor[key];
});
desc.enumerable = !!desc.enumerable;
desc.configurable = !!desc.configurable;

// 如果没有 value 属性或者没有 initializer 属性,表明是 getter 和 setter
if ("value" in desc || desc.initializer) {
 desc.writable = true;
}

那么 initializer 属性是什么呢?Object.getOwnPropertyDescriptor() 返回的对象并不具有这个属性呀,确实,这是 Babel 的 Class 为了与 decorator 配合而产生的一个属性,比如说对于下面这种代码:

class MyClass {
 @readonly
 born = Date.now();
}

function readonly(target, name, descriptor) {
 descriptor.writable = false;
 return descriptor;
}

var foo = new MyClass();
console.log(foo.born);

Babel 就会编译为:

// ...
(_descriptor = _applyDecoratedDescriptor(_class.prototype, "born", [readonly], {
 configurable: true,
 enumerable: true,
 writable: true,
 initializer: function() {
 return Date.now();
 }
}))
// ...

此时传入 _applyDecoratedDescriptor 函数的 descriptor 就具有 initializer 属性。

第二部分源码解析

接下是应用多个 decorators:

/**
 * 第二部分
 * @type {[type]}
 */
desc = decorators
 .slice()
 .reverse()
 .reduce(function(desc, decorator) {
 return decorator(target, property, desc) || desc;
 }, desc);

对于一个方法应用了多个 decorator,比如:

class MyClass {
 @unenumerable
 @readonly
 method() { }
}

Babel 会编译为:

_applyDecoratedDescriptor(
 _class.prototype,
 "method",
 [unenumerable, readonly],
 Object.getOwnPropertyDescriptor(_class.prototype, "method"),
 _class.prototype
)

在第二部分的源码中,执行了 reverse() 和 reduce() 操作,由此我们也可以发现,如果同一个方法有多个装饰器,会由内向外执行。

第三部分源码解析

/**
 * 第三部分
 * 设置要 decorators 的属性
 */
if (context && desc.initializer !== void 0) {
 desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
 desc.initializer = undefined;
}

if (desc.initializer === void 0) {
 Object["define" + "Property"](target, property, desc);
 desc = null;
}

return desc;

如果 desc 有 initializer 属性,意味着当装饰的是类的属性时,会将 value 的值设置为:

desc.initializer.call(context)

而 context 的值为 _class.prototype,之所以要 call(context),这也很好理解,因为有可能

class MyClass {
 @readonly
 value = this.getNum() + 1;

 getNum() {
 return 1;
 }
}

最后无论是装饰方法还是属性,都会执行:

Object["define" + "Property"](target, property, desc);

由此可见,装饰方法本质上还是使用 Object.defineProperty() 来实现的。

应用

1.log

为一个方法添加 log 函数,检查输入的参数:

class Math {
 @log
 add(a, b) {
 return a + b;
 }
}

function log(target, name, descriptor) {
 var oldValue = descriptor.value;

 descriptor.value = function(...args) {
 console.log(`Calling ${name} with`, args);
 return oldValue.apply(this, args);
 };

 return descriptor;
}

const math = new Math();

// Calling add with [2, 4]
math.add(2, 4);

再完善点:

let log = (type) => {
 return (target, name, descriptor) => {
 const method = descriptor.value;
 descriptor.value = (...args) => {
 console.info(`(${type}) 正在执行: ${name}(${args}) = ?`);
 let ret;
 try {
 ret = method.apply(target, args);
 console.info(`(${type}) 成功 : ${name}(${args}) => ${ret}`);
 } catch (error) {
 console.error(`(${type}) 失败: ${name}(${args}) => ${error}`);
 }
 return ret;
 }
 }
};

2.autobind

class Person {
 @autobind
 getPerson() {
 return this;
 }
}

let person = new Person();
let { getPerson } = person;

getPerson() === person;
// true

我们很容易想到的一个场景是 React 绑定事件的时候:

class Toggle extends React.Component {

 @autobind
 handleClick() {
 console.log(this)
 }

 render() {
 return (
 <button onClick={this.handleClick}>
 button
 </button>
 );
 }
}

我们来写这样一个 autobind 函数:

const { defineProperty, getPrototypeOf} = Object;

function bind(fn, context) {
 if (fn.bind) {
 return fn.bind(context);
 } else {
 return function __autobind__() {
 return fn.apply(context, arguments);
 };
 }
}

function createDefaultSetter(key) {
 return function set(newValue) {
 Object.defineProperty(this, key, {
 configurable: true,
 writable: true,
 enumerable: true,
 value: newValue
 });

 return newValue;
 };
}

function autobind(target, key, { value: fn, configurable, enumerable }) {
 if (typeof fn !== 'function') {
 throw new SyntaxError(`@autobind can only be used on functions, not: ${fn}`);
 }

 const { constructor } = target;

 return {
 configurable,
 enumerable,

 get() {

 /**
 * 使用这种方式相当于替换了这个函数,所以当比如
 * Class.prototype.hasOwnProperty(key) 的时候,为了正确返回
 * 所以这里做了 this 的判断
 */
 if (this === target) {
 return fn;
 }

 const boundFn = bind(fn, this);

 defineProperty(this, key, {
 configurable: true,
 writable: true,
 enumerable: false,
 value: boundFn
 });

 return boundFn;
 },
 set: createDefaultSetter(key)
 };
}

3.debounce

有的时候,我们需要对执行的方法进行防抖处理:

class Toggle extends React.Component {

 @debounce(500, true)
 handleClick() {
 console.log('toggle')
 }

 render() {
 return (
 <button onClick={this.handleClick}>
 button
 </button>
 );
 }
}

我们来实现一下:

function _debounce(func, wait, immediate) {

 var timeout;

 return function () {
 var context = this;
 var args = arguments;

 if (timeout) clearTimeout(timeout);
 if (immediate) {
  var callNow = !timeout;
  timeout = setTimeout(function(){
  timeout = null;
  }, wait)
  if (callNow) func.apply(context, args)
 }
 else {
  timeout = setTimeout(function(){
  func.apply(context, args)
  }, wait);
 }
 }
}

function debounce(wait, immediate) {
 return function handleDescriptor(target, key, descriptor) {
 const callback = descriptor.value;

 if (typeof callback !== 'function') {
 throw new SyntaxError('Only functions can be debounced');
 }

 var fn = _debounce(callback, wait, immediate)

 return {
 ...descriptor,
 value() {
 fn()
 }
 };
 }
}

4.time

用于统计方法执行的时间:

function time(prefix) {
 let count = 0;
 return function handleDescriptor(target, key, descriptor) {

 const fn = descriptor.value;

 if (prefix == null) {
 prefix = `${target.constructor.name}.${key}`;
 }

 if (typeof fn !== 'function') {
 throw new SyntaxError(`@time can only be used on functions, not: ${fn}`);
 }

 return {
 ...descriptor,
 value() {
 const label = `${prefix}-${count}`;
 count++;
 console.time(label);

 try {
  return fn.apply(this, arguments);
 } finally {
  console.timeEnd(label);
 }
 }
 }
 }
}

5.mixin

用于将对象的方法混入 Class 中:

const SingerMixin = {
 sing(sound) {
 alert(sound);
 }
};

const FlyMixin = {
 // All types of property descriptors are supported
 get speed() {},
 fly() {},
 land() {}
};

@mixin(SingerMixin, FlyMixin)
class Bird {
 singMatingCall() {
 this.sing('tweet tweet');
 }
}

var bird = new Bird();
bird.singMatingCall();
// alerts "tweet tweet"

mixin 的一个简单实现如下:

function mixin(...mixins) {
 return target => {
 if (!mixins.length) {
 throw new SyntaxError(`@mixin() class ${target.name} requires at least one mixin as an argument`);
 }

 for (let i = 0, l = mixins.length; i < l; i++) {
 const descs = Object.getOwnPropertyDescriptors(mixins[i]);
 const keys = Object.getOwnPropertyNames(descs);

 for (let j = 0, k = keys.length; j < k; j++) {
 const key = keys[j];

 if (!target.prototype.hasOwnProperty(key)) {
  Object.defineProperty(target.prototype, key, descs[key]);
 }
 }
 }
 };
}

6.redux

实际开发中,React 与 Redux 库结合使用时,常常需要写成下面这样。

class MyReactComponent extends React.Component {}

export default connect(mapStateToProps, mapDispatchToProps)(MyReactComponent);

有了装饰器,就可以改写上面的代码。

@connect(mapStateToProps, mapDispatchToProps)
export default class MyReactComponent extends React.Component {};

相对来说,后一种写法看上去更容易理解。

7.注意

以上我们都是用于修饰类方法,我们获取值的方式为:

const method = descriptor.value;

但是如果我们修饰的是类的实例属性,因为 Babel 的缘故,通过 value 属性并不能获取值,我们可以写成:

const value = descriptor.initializer && descriptor.initializer();

热心网友

蔚来是国内头部新势力制造汽车的企业,ES8带着这种激进的家庭式设计语言进入市场时引发争议,但随着时间的推移,车迷也逐渐适应了这种设计,此后ES6以均衡的身材对这种设计语言做出了更加精致的解释。从车身材料到油漆,ES6表现出了良好的质感和高档感。另外,该车提供8种油漆颜色,只有星云紫1万韩元,其他7种颜色免费。

特斯拉是全球新能源市场的龙头企业,极简设计也*了粉丝对传统汽车设计的认识,很多甚至连新势力都争先恐后地模仿。ModelY更像是“KOLANmodel  3”。新车延续了家庭式设计,但总觉得奇怪,有点生动,没有新车型需要具备的自己的特色,不能在视觉上显得有魅力。这辆车提供5种汽车油漆颜色,标准纯黑色汽车油漆,其他4种颜色的汽车油漆选择价格为8000韩元。标准19英寸轮子,20英寸轮子的选择价格是8000韩元。从设计角度来看,ES6更加精致,车身材料和油漆的质感也很好。ModelY继续特斯拉家族的极简设计语言,但缺乏新车型需要具备的特点,各种汽车油漆都要挑选。

排在第9位。在所有车型销量排名中,这一成绩并不突出,但值得注意的是,未来ES6是最畅销的电动汽车SUV。蔚来汽车是国内刚刚崛起的造车新势力,蔚来ES6是第二种。作为新产品,如果能杀死销量前10名的名单,到底有什么吸引力?蔚来ES6是纯电动中型SUV车,官方介绍价为34.36万至50.1万韩元。价格上确实让笔者感到惊讶。这个价格可以说是豪车价格,但未来ES6销量表明市场对这辆车仍然认可。

从ES6的外观来看,其设计保持前卫的风格,整体遵循ES8的设计。ES6可以说是迷你版本的ES8。只是在细节方面做了一些修改。前脸没有铬装饰,看起来很顺溜,大灯的轮廓也不同。除了车头,ES6的车尾,特别是车尾45是整辆车识别度最高的地方,经过简洁的线条处理,给人一种非常优雅的视觉感觉。符合车身的颜色,是未来科技车的感觉和适当的安置车。总的来说,ES6的外观非常品牌化,好看,辨识力强。在路上跑,这就是ES6。

热心网友

因为蔚来ES6的配置很高,而且技术比较先进,研发成本也很高,所以价格就高了。

热心网友

特别是我们国家特别高端的品牌,而且车辆做的也非常的好看,也会有跑车,而且性价比也特别高,所以价格才会这么贵。

热心网友

纯电动车价格这么高,最主要的原因,它做的这个做工很精细,外观包括里面的座椅都是纯皮的,而且非常的高档,不输那种,燃油车。

热心网友

做工太差,都是革的味道大,椅子特硬,内饰很low

热心网友

拥有纯电动车是趋势。
看了ES6这款车,外观内饰都显高级感,加上高科技的配置和强大的性能,如果花40万买老气的宝马奔驰车,真不如来辆ES6更拉风。

热心网友

1.尺寸:比奥迪Q5L大一圈
2.材料:全铝车身,全铝底盘
3.配置:全系标配空气悬架
4.性能:百公里加速4.7s,奥迪SQ5才能达到
5.服务,科技,智能

热心网友

因为韭菜傻啊

热心网友

想多赚你的钱呗!这都不知道在瞎写什么呀!

热心网友

装*高档车嘛!兔子尾巴长不了了!

热心网友

这还用问,割韭菜难道不用快刀吗?

热心网友

外型这么笨,一点流畅感都没有,买这车不知道怎么想的。一看就是廉价货,还卖这么高价格。

热心网友

我认为是由于这款车是做工非常的好,而且有非常多的高科技配置,安全系数非常高,导致售价昂贵。

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com